From: Nick Bowler Date: Wed, 17 Apr 2024 02:34:19 +0000 (-0400) Subject: cdecl99-1.3 bash-5 hotfix X-Git-Url: https://git.draconx.ca/gitweb/homepage.git/commitdiff_plain/HEAD?hp=3b0f4240021823cd3b02bc06a70155e9e9b54b14;ds=sidebyside cdecl99-1.3 bash-5 hotfix Turns out that prior to release the package was not tested on any systems where /bin/sh is bash-5, and the configure script hits a parser bug in this shell regarding for loops in case statements. A workaround is to set CONFIG_SHELL environment variable to some other shell without this bug. But if that's not possible, this patch can be applied to avoid the bug. --- diff --git a/.gitmodules b/.gitmodules index d345e88..f24b460 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "gitmodules/cdecl99"] path = gitmodules/cdecl99 url = https://git.draconx.ca/cdecl99.git +[submodule "gitmodules/rrace"] + path = gitmodules/rrace + url = https://git.draconx.ca/rrace.git +[submodule "gitmodules/rarpd-dx"] + path = gitmodules/rarpd-dx + url = https://git.draconx.ca/rarpd-dx.git diff --git a/Rules b/Rules index d3247cb..1aa5907 100644 --- a/Rules +++ b/Rules @@ -1,6 +1,6 @@ #!/usr/bin/env ruby # -# Copyright © 2018-2020 Nick Bowler +# Copyright © 2018-2022 Nick Bowler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -68,20 +68,24 @@ preprocess do @items.create("", attrs, "#{dir}/index.lst") end + + create_wkd_items(@items["/pubring.gpg"]) + create_hkp_items(@items["/pubring.gpg"]) end postprocess do # Gzip all text items for nginx http_static - if !ENV['GZIP_SITE'].to_s.empty? + gzip_site = !ENV['GZIP_SITE'].to_s.empty? + if gzip_site reps = @items.flat_map(&:reps).each do |rep| - file = rep.raw_path - next if !file or rep.binary? - - if system("gzip", "-ck9", file, [:out]=>[file + ".gz.tmp", "wb"]) - system("touch", "-r", file, file + ".gz.tmp") - File.rename(file + ".gz.tmp", file + ".gz") - else - File.unlink(file + ".gz.tmp") + next if rep.binary? + rep.instance_variable_get(:@item_rep).raw_paths[:last].each do |f| + if system("gzip", "-nck9", f, [:out]=>["#{f}.gz.tmp", "wb"]) + system("touch", "-r", f, "#{f}.gz.tmp") + File.rename("#{f}.gz.tmp", "#{f}.gz") + else + File.unlink("#{f}.gz.tmp") + end end end end @@ -100,6 +104,7 @@ postprocess do # Find output reps corresponding to this key, if any item.reps.each do |rep| + next if rep.raw_path.nil? next unless FileUtils.identical?(item.raw_filename, rep.raw_path) @@ -179,11 +184,21 @@ compile '/license/cc*.xhtml' do end compile '/images/*.jpg', rep: :large do + w, h = FastImage.size(item.raw_filename) filename = item.identifier.without_ext + '-t1200.' + item.identifier.ext - filter :imgresize, width: 1200, height: 1200, cache: filename + filter :imgresize, width: [w, 1200].min, height: [h, 1200].min, cache: filename write filename end +compile '/images/*.jpg', rep: :medium do + w, h = FastImage.size(item.raw_filename) + filename = item.identifier.without_ext + '-t800.' + item.identifier.ext + if w > 900 or h > 900 + filter :imgresize, width: 800, height: 800, cache: filename + write filename + end +end + compile '/images/*.jpg', rep: :info do filter :imginfo layout '/imginfo.xsl' @@ -195,16 +210,39 @@ compile '/images/*.jpg', rep: :info do end compile '/**/*.scss' do - filter :sass, syntax: :scss + filter :sass, syntax: :scss, load_paths: ["."] filter :css_source, uribase: \ "https://git.draconx.ca/gitweb/homepage.git/blob/" + @item[:gitrev] + ":" filter :css_clean_selectors, \ preserve_comments: true, \ preserve_hacks: true + snapshot :before_darkmode + filter :css_darkmode write @item.identifier.without_ext + '.css' end +compile '/style.scss', rep: :dark do + filter :compiled_content, snapshot: :before_darkmode + filter :css_darkmode, alternate: true + write "/dark.css" +end + +compile '/gpg/*' do + filter :wkd_export_armor + write "/pubring/#{@item.identifier.components.last}.asc" + write "/pubring/#{@item[:id64]}.asc" if @item[:id64] + write "/pubring/#{@item[:id32]}.asc" if @item[:id32] +end + +compile '/gpg/*', rep: :hu do + if @item[:wkd_hash] + filter :wkd_export + write "/pubring/wkd/" + @item[:wkd_hash] + end +end +ignore '/*.gpg' + compile '/**/*.svg' do filter :scour, comment_stripping: true write @item.identifier.to_s diff --git a/content/archive/cdecl99/cdecl99-1.2.tar.gz b/content/archive/cdecl99/cdecl99-1.2.tar.gz new file mode 120000 index 0000000..f2992a8 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.2.tar.gz @@ -0,0 +1 @@ +../../../.git/annex/objects/2f/p1/SHA512-s966058--01e7f4c09c32beac469900895d0e3115ceb083bc1e273cff30cd9a7b0427359c826e7d20d0d578af92ee88598f66f629f8c756ac8b5fa38f5f930e0f77d2ac76/SHA512-s966058--01e7f4c09c32beac469900895d0e3115ceb083bc1e273cff30cd9a7b0427359c826e7d20d0d578af92ee88598f66f629f8c756ac8b5fa38f5f930e0f77d2ac76 \ No newline at end of file diff --git a/content/archive/cdecl99/cdecl99-1.2.tar.gz.sig b/content/archive/cdecl99/cdecl99-1.2.tar.gz.sig new file mode 120000 index 0000000..42a4117 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.2.tar.gz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/pj/JW/SHA512-s310--d32edf921631e3af7fcc7aacb9579c32215f86696e83d4bbead5ed998b1ed786a640e5e16bc7b9bfbf25980907396f8d8510bca70d7039beb908a030b30f32c3/SHA512-s310--d32edf921631e3af7fcc7aacb9579c32215f86696e83d4bbead5ed998b1ed786a640e5e16bc7b9bfbf25980907396f8d8510bca70d7039beb908a030b30f32c3 \ No newline at end of file diff --git a/content/archive/cdecl99/cdecl99-1.2.tar.xz b/content/archive/cdecl99/cdecl99-1.2.tar.xz new file mode 120000 index 0000000..7330ce4 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.2.tar.xz @@ -0,0 +1 @@ +../../../.git/annex/objects/wg/1j/SHA512-s634148--a24f095fd66e0c7fceb1b089de92d5a96d8d21c2c59d5f91da8374ca1465f65041d806bcd5cd1299778dd4d25204390f437b481f8cb07b9fa0a88cecf19185c2/SHA512-s634148--a24f095fd66e0c7fceb1b089de92d5a96d8d21c2c59d5f91da8374ca1465f65041d806bcd5cd1299778dd4d25204390f437b481f8cb07b9fa0a88cecf19185c2 \ No newline at end of file diff --git a/content/archive/cdecl99/cdecl99-1.2.tar.xz.sig b/content/archive/cdecl99/cdecl99-1.2.tar.xz.sig new file mode 120000 index 0000000..d70b59e --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.2.tar.xz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/PV/QZ/SHA512-s310--204a5c7003d96860a28671778099578a2f89d5f0c5d8b0a0bf883762555f0db7ca202248630cf2c07858d86d7faf450f566103e94676cedcafbe0fbcafa7ac8f/SHA512-s310--204a5c7003d96860a28671778099578a2f89d5f0c5d8b0a0bf883762555f0db7ca202248630cf2c07858d86d7faf450f566103e94676cedcafbe0fbcafa7ac8f \ No newline at end of file diff --git a/content/archive/cdecl99/cdecl99-1.3-bash5-fix.patch b/content/archive/cdecl99/cdecl99-1.3-bash5-fix.patch new file mode 100644 index 0000000..0ffc323 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.3-bash5-fix.patch @@ -0,0 +1,49 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 +NotDashEscaped: You need gpg to verify this message + +The configure script included with the cdecl99-1.3 release fails on +bash-5 due to a parser bug in this shell. On affected systems, a +message similar to the following may be seen when running configure: + + ./configure: line 6631: syntax error near unexpected token `do' + ./configure: line 6631: `do' + +You can work around the problem by setting the CONFIG_SHELL environment +variable to some other shell before running configure; otherwise you can +apply this patch file with a command such as: + + % cd cdecl99-1.3 + % patch -p1 &6 + else + dx_cv_have_alignas=no +! for _dx_alignas +! in '_Alignas(X)' '__attribute__((__aligned__(X)))' '__declspec(align(X))' + do + if ac_fn_c_compute_int "$LINENO" "sizeof (struct { char a; char ALIGNAS_TEST(4) b; }) >= 8" "_dx_tmp" "#include + #define ALIGNAS_TEST(X) $_dx_alignas +--- 6626,6632 ---- + $as_echo_n "(cached) " >&6 + else + dx_cv_have_alignas=no +! for _dx_alignas in '_Alignas(X)' '__attribute__((__aligned__(X)))' '__declspec(align(X))' + do + if ac_fn_c_compute_int "$LINENO" "sizeof (struct { char a; char ALIGNAS_TEST(4) b; }) >= 8" "_dx_tmp" "#include + #define ALIGNAS_TEST(X) $_dx_alignas +-----BEGIN PGP SIGNATURE----- + +iQEzBAEBCAAdFiEEJagcgrvBtB9dtMuDW0XT0YW44fYFAmYfNBUACgkQW0XT0YW4 +4famBQf9GhDZJGOvrkDB5dGWwieXqFCWXJBbATVbY8JmY5wJupke5MqvDEQJ3tBr +A2YIcQZ67+KjA2LwWTTQhQgKkveQs1HWFdTDrHnhTm4dF4jZdlxwVK3K3kHCcref +uW+vl/6C9YkKcVcbf8OeHT4JVgYv2h7XRKW69XIB6lchdMc6rGNeStuCHyuGKYWG +7n3WH9bA5OBPmPAd6yUPmU4urWBHjZwxyTaFBYBO7T+9R3Q4KvvyzCfxt1JxTUPS +SmiQC1B0gg16/N2XJzCmnBsaVXSHdsvt8UrZeIZyWipejqtb2UR1MVnVToz/83NO +gh5tyhxXnYiQgRqd2/uRg9z+GzziDw== +=/RXF +-----END PGP SIGNATURE----- diff --git a/content/archive/cdecl99/cdecl99-1.3.tar.gz b/content/archive/cdecl99/cdecl99-1.3.tar.gz new file mode 120000 index 0000000..b948234 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.3.tar.gz @@ -0,0 +1 @@ +../../../.git/annex/objects/v9/65/SHA512-s897087--54ab0ce2db34beaee220cbed936b009added5a51b901c2251c7767df6e63a84a8ce6f59b59ec6b00925c2845674a8d5ef02e620bd5eb8074b52cd07441c005cd/SHA512-s897087--54ab0ce2db34beaee220cbed936b009added5a51b901c2251c7767df6e63a84a8ce6f59b59ec6b00925c2845674a8d5ef02e620bd5eb8074b52cd07441c005cd \ No newline at end of file diff --git a/content/archive/cdecl99/cdecl99-1.3.tar.gz.sig b/content/archive/cdecl99/cdecl99-1.3.tar.gz.sig new file mode 120000 index 0000000..57d10b0 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.3.tar.gz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/4v/p3/SHA512-s310--b4b196e4df43c18634ba5dcc8823cf677931ceb0bd2965713db0a078d29e979c601f190e854caed60af7d7249a60f2b39cbd86c1bcdb9b43827945aa5acd5669/SHA512-s310--b4b196e4df43c18634ba5dcc8823cf677931ceb0bd2965713db0a078d29e979c601f190e854caed60af7d7249a60f2b39cbd86c1bcdb9b43827945aa5acd5669 \ No newline at end of file diff --git a/content/archive/cdecl99/cdecl99-1.3.tar.lz b/content/archive/cdecl99/cdecl99-1.3.tar.lz new file mode 120000 index 0000000..8382932 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.3.tar.lz @@ -0,0 +1 @@ +../../../.git/annex/objects/3j/wf/SHA512-s591522--11f04eeda91ef127f6e3d5ef5e2cbb135e6a1f46a138640decbe80ed687c9fd2110a94b2fd883d8d0125704b36760c89cf41aeb5005f7965721b85fb55826b6c/SHA512-s591522--11f04eeda91ef127f6e3d5ef5e2cbb135e6a1f46a138640decbe80ed687c9fd2110a94b2fd883d8d0125704b36760c89cf41aeb5005f7965721b85fb55826b6c \ No newline at end of file diff --git a/content/archive/cdecl99/cdecl99-1.3.tar.lz.sig b/content/archive/cdecl99/cdecl99-1.3.tar.lz.sig new file mode 120000 index 0000000..fbb9bb9 --- /dev/null +++ b/content/archive/cdecl99/cdecl99-1.3.tar.lz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/3k/Mp/SHA512-s310--5c1d52ff133aeaaa7be59f5ec394ecf95d29341eb491909a12412f246b1d88251e6449aab9385797d0d3bf23eb6ff8fd8eedf80dbc446c4d61f5dbf43dc45ed4/SHA512-s310--5c1d52ff133aeaaa7be59f5ec394ecf95d29341eb491909a12412f246b1d88251e6449aab9385797d0d3bf23eb6ff8fd8eedf80dbc446c4d61f5dbf43dc45ed4 \ No newline at end of file diff --git a/content/archive/rarpd-dx/rarpd-dx-1.tar.gz b/content/archive/rarpd-dx/rarpd-dx-1.tar.gz new file mode 120000 index 0000000..5ed165b --- /dev/null +++ b/content/archive/rarpd-dx/rarpd-dx-1.tar.gz @@ -0,0 +1 @@ +../../../.git/annex/objects/fv/p8/SHA512-s105283--742eeeccb8eba6daea7294ab696cd9e2ad92e84c1b81d5512c8654c5d1df258d5584c360569fe41b73b84757f0cfea93d5da1b67de59b4b920610009068b85de/SHA512-s105283--742eeeccb8eba6daea7294ab696cd9e2ad92e84c1b81d5512c8654c5d1df258d5584c360569fe41b73b84757f0cfea93d5da1b67de59b4b920610009068b85de \ No newline at end of file diff --git a/content/archive/rarpd-dx/rarpd-dx-1.tar.gz.sig b/content/archive/rarpd-dx/rarpd-dx-1.tar.gz.sig new file mode 120000 index 0000000..6c7a819 --- /dev/null +++ b/content/archive/rarpd-dx/rarpd-dx-1.tar.gz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/g6/j8/SHA512-s310--b40653638706881f135868329359e00c0c55134fadebebb4572f93de79c3d2ff39f6c0af7ad5dcc16f1ed9dd3b2afdca8b9af8dbd071a6b19afabc104658feb6/SHA512-s310--b40653638706881f135868329359e00c0c55134fadebebb4572f93de79c3d2ff39f6c0af7ad5dcc16f1ed9dd3b2afdca8b9af8dbd071a6b19afabc104658feb6 \ No newline at end of file diff --git a/content/archive/rarpd-dx/rarpd-dx-1.tar.lz b/content/archive/rarpd-dx/rarpd-dx-1.tar.lz new file mode 120000 index 0000000..cbf3770 --- /dev/null +++ b/content/archive/rarpd-dx/rarpd-dx-1.tar.lz @@ -0,0 +1 @@ +../../../.git/annex/objects/65/5W/SHA512-s82601--3642314e7390074a50f080c1d3039b1db6d57895efd40a8285a2cc95f5777962282b11edfee3a17caa10fe9c4dc129729fe4b3c6c02ddb411d1b6d57186e1278/SHA512-s82601--3642314e7390074a50f080c1d3039b1db6d57895efd40a8285a2cc95f5777962282b11edfee3a17caa10fe9c4dc129729fe4b3c6c02ddb411d1b6d57186e1278 \ No newline at end of file diff --git a/content/archive/rarpd-dx/rarpd-dx-1.tar.lz.sig b/content/archive/rarpd-dx/rarpd-dx-1.tar.lz.sig new file mode 120000 index 0000000..c219a09 --- /dev/null +++ b/content/archive/rarpd-dx/rarpd-dx-1.tar.lz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/k5/6V/SHA512-s310--530702e16b139db74862244dde8ddbb8d8618c462b935e3e9bc02fdf7e0fa58ff4d952aa444acfb524e4e4c0f2317a7c20a6cc65ec64ff2f9442b9a5753cfafe/SHA512-s310--530702e16b139db74862244dde8ddbb8d8618c462b935e3e9bc02fdf7e0fa58ff4d952aa444acfb524e4e4c0f2317a7c20a6cc65ec64ff2f9442b9a5753cfafe \ No newline at end of file diff --git a/content/archive/slotifier/slotifier-1.2.tar.gz b/content/archive/slotifier/slotifier-1.2.tar.gz new file mode 120000 index 0000000..c78d3e8 --- /dev/null +++ b/content/archive/slotifier/slotifier-1.2.tar.gz @@ -0,0 +1 @@ +../../../.git/annex/objects/mX/vg/SHA512-s757803--1b1861ba2d89aa6aa947950fb99320297d07a67f0d412f90d5762c887b1df2f24f0771b7e94a9e7b22f89217be9c311f256e241653585d2b26cbfdb0b39a96b1/SHA512-s757803--1b1861ba2d89aa6aa947950fb99320297d07a67f0d412f90d5762c887b1df2f24f0771b7e94a9e7b22f89217be9c311f256e241653585d2b26cbfdb0b39a96b1 \ No newline at end of file diff --git a/content/archive/slotifier/slotifier-1.2.tar.gz.sig b/content/archive/slotifier/slotifier-1.2.tar.gz.sig new file mode 120000 index 0000000..adfd8cc --- /dev/null +++ b/content/archive/slotifier/slotifier-1.2.tar.gz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/K5/0W/SHA512-s310--f75452f84715516f4c2cbfadc7d154104b30c9635b7a0440cc78aff823faed8f38c2e73a20b91b8146c49c17109f27ea37ff62933d9cd29659a41252a27775b5/SHA512-s310--f75452f84715516f4c2cbfadc7d154104b30c9635b7a0440cc78aff823faed8f38c2e73a20b91b8146c49c17109f27ea37ff62933d9cd29659a41252a27775b5 \ No newline at end of file diff --git a/content/archive/slotifier/slotifier-1.2.tar.xz b/content/archive/slotifier/slotifier-1.2.tar.xz new file mode 120000 index 0000000..bd19166 --- /dev/null +++ b/content/archive/slotifier/slotifier-1.2.tar.xz @@ -0,0 +1 @@ +../../../.git/annex/objects/jF/0k/SHA512-s489248--798c964e4d7e22fe576f658aa8f13b3a207ed9d079b04a6792c51960587291d9b3f6a2295b5e7b1a9bdfe3315e8c8f808ac3c20929f7f6b86a0fde7e9897959d/SHA512-s489248--798c964e4d7e22fe576f658aa8f13b3a207ed9d079b04a6792c51960587291d9b3f6a2295b5e7b1a9bdfe3315e8c8f808ac3c20929f7f6b86a0fde7e9897959d \ No newline at end of file diff --git a/content/archive/slotifier/slotifier-1.2.tar.xz.sig b/content/archive/slotifier/slotifier-1.2.tar.xz.sig new file mode 120000 index 0000000..7e12c78 --- /dev/null +++ b/content/archive/slotifier/slotifier-1.2.tar.xz.sig @@ -0,0 +1 @@ +../../../.git/annex/objects/Z8/MM/SHA512-s310--52d05160240e7d9701768f17c9661e97f9d729709830dc400f884bc31744e589b192ea3a6c230ef0ecb3a4a94df528bad8fc33d86aa2a4e59c88fd173663b4e0/SHA512-s310--52d05160240e7d9701768f17c9661e97f9d729709830dc400f884bc31744e589b192ea3a6c230ef0ecb3a4a94df528bad8fc33d86aa2a4e59c88fd173663b4e0 \ No newline at end of file diff --git a/content/icons/down.svg b/content/icons/down.svg index 95b82af..0c05c06 100644 --- a/content/icons/down.svg +++ b/content/icons/down.svg @@ -67,6 +67,7 @@ diff --git a/content/icons/folder.svg b/content/icons/folder.svg index 79b25c3..ff2f8d7 100644 --- a/content/icons/folder.svg +++ b/content/icons/folder.svg @@ -42,6 +42,7 @@ r="117.14286" /> diff --git a/content/icons/up.svg b/content/icons/up.svg index 54263df..63e8db3 100644 --- a/content/icons/up.svg +++ b/content/icons/up.svg @@ -89,6 +89,7 @@ diff --git a/content/images/eclipse-20210610-clouds.jpg b/content/images/eclipse-20210610-clouds.jpg new file mode 120000 index 0000000..0fb46fb --- /dev/null +++ b/content/images/eclipse-20210610-clouds.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/jf/z5/SHA512-s257188--05f166f1b15bb984ed150ea4a87e369f58dccdb3a561ae0ec2975da1e194bffc4da0a36dc14d2c6d881bc1424d1eff66241701291bab666f2a95beac66412415/SHA512-s257188--05f166f1b15bb984ed150ea4a87e369f58dccdb3a561ae0ec2975da1e194bffc4da0a36dc14d2c6d881bc1424d1eff66241701291bab666f2a95beac66412415 \ No newline at end of file diff --git a/content/images/eclipse-20210610-clouds.yaml b/content/images/eclipse-20210610-clouds.yaml new file mode 100644 index 0000000..dd687fa --- /dev/null +++ b/content/images/eclipse-20210610-clouds.yaml @@ -0,0 +1,7 @@ +--- +title: 2021-06-10 Partial Eclipse Through Clouds +copyright: 2021 Nick Bowler +license: cc-by-sa-4.0 +description: | + Almost 20 minutes after the maximum eclipse, the clouds begin to come back + to rejoin the fun. diff --git a/content/images/eclipse-20210610-farewell.jpg b/content/images/eclipse-20210610-farewell.jpg new file mode 120000 index 0000000..4131a74 --- /dev/null +++ b/content/images/eclipse-20210610-farewell.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/00/F8/SHA512-s107816--4e990963d97828f1d68bca567d8f5ebd95cbca92106d7b185c3fe32d0bb7ee0f402273f1854929181526c98b0c0a83f8c6befb63bf4855be39e617814c70f38c/SHA512-s107816--4e990963d97828f1d68bca567d8f5ebd95cbca92106d7b185c3fe32d0bb7ee0f402273f1854929181526c98b0c0a83f8c6befb63bf4855be39e617814c70f38c \ No newline at end of file diff --git a/content/images/eclipse-20210610-farewell.yaml b/content/images/eclipse-20210610-farewell.yaml new file mode 100644 index 0000000..a5ce817 --- /dev/null +++ b/content/images/eclipse-20210610-farewell.yaml @@ -0,0 +1,6 @@ +--- +title: 2021-06-10 Fare Thee Well, Eclipse +copyright: 2021 Nick Bowler +license: cc-by-sa-4.0 +description: | + The spectacle is mostly over as the sun returns to hiding behind some clouds. diff --git a/content/images/eclipse-20210610-max.jpg b/content/images/eclipse-20210610-max.jpg new file mode 120000 index 0000000..4a36ece --- /dev/null +++ b/content/images/eclipse-20210610-max.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/Qv/71/SHA512-s456326--212c721a3ee49a09a1b7f55fd3a7db962cec291f2e1c9274b954e029bf41451476d5aef545596af7f1bce45132541a7a9760357bdc7b03ff50a8bf83d40b9d80/SHA512-s456326--212c721a3ee49a09a1b7f55fd3a7db962cec291f2e1c9274b954e029bf41451476d5aef545596af7f1bce45132541a7a9760357bdc7b03ff50a8bf83d40b9d80 \ No newline at end of file diff --git a/content/images/eclipse-20210610-max.yaml b/content/images/eclipse-20210610-max.yaml new file mode 100644 index 0000000..535ac54 --- /dev/null +++ b/content/images/eclipse-20210610-max.yaml @@ -0,0 +1,7 @@ +--- +title: 2021-06-10 Maximum Eclipse from Ottawa +copyright: 2021 Nick Bowler +license: cc-by-sa-4.0 +description: | + Greatest eclipse as seen from Ottawa on 2021-06-10, with approximately 80% of + the sun obscured. diff --git a/content/images/eclipse-20210610-sunrise.jpg b/content/images/eclipse-20210610-sunrise.jpg new file mode 120000 index 0000000..c511776 --- /dev/null +++ b/content/images/eclipse-20210610-sunrise.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/V5/kz/SHA512-s55143--bb4418266b4e21b6a4b3f39f7aec3deb6593ce0fdaf3b7d60feca81e7398165315b69e989012e583352ad2d4960f890099bd570f39d7e286b14a07bcf6a70534/SHA512-s55143--bb4418266b4e21b6a4b3f39f7aec3deb6593ce0fdaf3b7d60feca81e7398165315b69e989012e583352ad2d4960f890099bd570f39d7e286b14a07bcf6a70534 \ No newline at end of file diff --git a/content/images/eclipse-20210610-sunrise.yaml b/content/images/eclipse-20210610-sunrise.yaml new file mode 100644 index 0000000..c85adbb --- /dev/null +++ b/content/images/eclipse-20210610-sunrise.yaml @@ -0,0 +1,7 @@ +--- +title: 2021-06-10 Sunrise from Ottawa +copyright: 2021 Nick Bowler +license: cc-by-sa-4.0 +description: | + The eclipse is well under way at sunrise. Some clouds obscure the horizon + but after about 10 minutes the sun begins to rise above them. diff --git a/content/images/eclipse-20220515-223224.jpg b/content/images/eclipse-20220515-223224.jpg new file mode 120000 index 0000000..ecd014e --- /dev/null +++ b/content/images/eclipse-20220515-223224.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/7V/6K/SHA512-s62206--3c7b5e8560109819d8616fbb77e86dfe275da79bee14a99958b849e2d45fd82196a3aa88d06f7d4bb6a5258a9ee025f5505ee120388c5066dfa1b09e3c61772f/SHA512-s62206--3c7b5e8560109819d8616fbb77e86dfe275da79bee14a99958b849e2d45fd82196a3aa88d06f7d4bb6a5258a9ee025f5505ee120388c5066dfa1b09e3c61772f \ No newline at end of file diff --git a/content/images/eclipse-20220515-223224.yaml b/content/images/eclipse-20220515-223224.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-223224.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-223904.jpg b/content/images/eclipse-20220515-223904.jpg new file mode 120000 index 0000000..8f52052 --- /dev/null +++ b/content/images/eclipse-20220515-223904.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/z1/gk/SHA512-s67272--ee40a65584c53a7bdf481f66b0633bfcb5612a832b6d033bd0e049d3b4556641168e4842e95a465031dccfb8516635c861ae64065a733cf7392bcbf88df790f3/SHA512-s67272--ee40a65584c53a7bdf481f66b0633bfcb5612a832b6d033bd0e049d3b4556641168e4842e95a465031dccfb8516635c861ae64065a733cf7392bcbf88df790f3 \ No newline at end of file diff --git a/content/images/eclipse-20220515-223904.yaml b/content/images/eclipse-20220515-223904.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-223904.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-225442.jpg b/content/images/eclipse-20220515-225442.jpg new file mode 120000 index 0000000..071bd37 --- /dev/null +++ b/content/images/eclipse-20220515-225442.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/56/0v/SHA512-s62547--acaa868e092acac5329ff17af7b36c6715b0b27c0c7e856199a5c0137fd6d27fbeb3cda7b2e71f6e45538108ecc3dc7782ea7a7ec332d2f903e79b2875d90b7c/SHA512-s62547--acaa868e092acac5329ff17af7b36c6715b0b27c0c7e856199a5c0137fd6d27fbeb3cda7b2e71f6e45538108ecc3dc7782ea7a7ec332d2f903e79b2875d90b7c \ No newline at end of file diff --git a/content/images/eclipse-20220515-225442.yaml b/content/images/eclipse-20220515-225442.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-225442.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-230507.jpg b/content/images/eclipse-20220515-230507.jpg new file mode 120000 index 0000000..0b86aad --- /dev/null +++ b/content/images/eclipse-20220515-230507.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/V2/pq/SHA512-s59928--c64ed7765384fd5bd27b61ccf2e927ae38dbce4737d50890c173a7e2b32ab47fea76129d804eb22462582d27e95d1703bb5c29e07e881ee4d91f3c9739f56e9a/SHA512-s59928--c64ed7765384fd5bd27b61ccf2e927ae38dbce4737d50890c173a7e2b32ab47fea76129d804eb22462582d27e95d1703bb5c29e07e881ee4d91f3c9739f56e9a \ No newline at end of file diff --git a/content/images/eclipse-20220515-230507.yaml b/content/images/eclipse-20220515-230507.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-230507.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-231141.jpg b/content/images/eclipse-20220515-231141.jpg new file mode 120000 index 0000000..597a301 --- /dev/null +++ b/content/images/eclipse-20220515-231141.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/pq/vJ/SHA512-s61153--ca215607a273fee73a79513d2e53ca76225a428f2ee2898e7616798802dac52703b24551644f235eca14660a32f5959b59f0960157748d73d0ccc6513a501c08/SHA512-s61153--ca215607a273fee73a79513d2e53ca76225a428f2ee2898e7616798802dac52703b24551644f235eca14660a32f5959b59f0960157748d73d0ccc6513a501c08 \ No newline at end of file diff --git a/content/images/eclipse-20220515-231141.yaml b/content/images/eclipse-20220515-231141.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-231141.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-231939.jpg b/content/images/eclipse-20220515-231939.jpg new file mode 120000 index 0000000..111cfce --- /dev/null +++ b/content/images/eclipse-20220515-231939.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/qK/wK/SHA512-s42573--ac7ec2f106c7924a66b021eac1d8e53d0f480fda49adb27ce6dfe715c05d4cd463a41ec4a8ce8dca50b186f0ef719b201b0d757d13e8f4f793d61f24ee68c2bc/SHA512-s42573--ac7ec2f106c7924a66b021eac1d8e53d0f480fda49adb27ce6dfe715c05d4cd463a41ec4a8ce8dca50b186f0ef719b201b0d757d13e8f4f793d61f24ee68c2bc \ No newline at end of file diff --git a/content/images/eclipse-20220515-231939.yaml b/content/images/eclipse-20220515-231939.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-231939.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-232447.jpg b/content/images/eclipse-20220515-232447.jpg new file mode 120000 index 0000000..237113e --- /dev/null +++ b/content/images/eclipse-20220515-232447.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/41/06/SHA512-s45985--47c57854f6bf0235a0beceadda5bd3e44e216ca10e4f48f1a15104d48c353405eca7d8b6834b411f2ea4d35e97fed5e83bc090db3902d2cdbbf40b6e025c6d8e/SHA512-s45985--47c57854f6bf0235a0beceadda5bd3e44e216ca10e4f48f1a15104d48c353405eca7d8b6834b411f2ea4d35e97fed5e83bc090db3902d2cdbbf40b6e025c6d8e \ No newline at end of file diff --git a/content/images/eclipse-20220515-232447.yaml b/content/images/eclipse-20220515-232447.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-232447.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-232709.jpg b/content/images/eclipse-20220515-232709.jpg new file mode 120000 index 0000000..2f3f5f7 --- /dev/null +++ b/content/images/eclipse-20220515-232709.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/7w/J8/SHA512-s46545--ce81c5cf09098e2c3d9566b7a23705d29e2db6c08f2dc3a5129294b546f814f8f4c84a28a4a82a236d327f55bf2e8930fa5afea2f67001ce5e565a35aa89eb39/SHA512-s46545--ce81c5cf09098e2c3d9566b7a23705d29e2db6c08f2dc3a5129294b546f814f8f4c84a28a4a82a236d327f55bf2e8930fa5afea2f67001ce5e565a35aa89eb39 \ No newline at end of file diff --git a/content/images/eclipse-20220515-232709.yaml b/content/images/eclipse-20220515-232709.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-232709.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-233454.jpg b/content/images/eclipse-20220515-233454.jpg new file mode 120000 index 0000000..fec7426 --- /dev/null +++ b/content/images/eclipse-20220515-233454.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/k1/5F/SHA512-s45317--093734cb997e659c34ccceff0899ffa33b42da32c10b8f1a26ca7fc7bebcde982835f85033731c1a17c43c90a695a6e5081721d68a07109bd090fe2dced56021/SHA512-s45317--093734cb997e659c34ccceff0899ffa33b42da32c10b8f1a26ca7fc7bebcde982835f85033731c1a17c43c90a695a6e5081721d68a07109bd090fe2dced56021 \ No newline at end of file diff --git a/content/images/eclipse-20220515-233454.yaml b/content/images/eclipse-20220515-233454.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-233454.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-233803.jpg b/content/images/eclipse-20220515-233803.jpg new file mode 120000 index 0000000..34a8b24 --- /dev/null +++ b/content/images/eclipse-20220515-233803.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/P3/Z3/SHA512-s61296--0fbbe13c91dd55730ab794c173ef89cb67236af9815183b89cb4cb2422d96a69b7642b545a9759c6d701c101468276e59a63fea597b6bdd8cd591b12b5dddede/SHA512-s61296--0fbbe13c91dd55730ab794c173ef89cb67236af9815183b89cb4cb2422d96a69b7642b545a9759c6d701c101468276e59a63fea597b6bdd8cd591b12b5dddede \ No newline at end of file diff --git a/content/images/eclipse-20220515-233803.yaml b/content/images/eclipse-20220515-233803.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-233803.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-234126.jpg b/content/images/eclipse-20220515-234126.jpg new file mode 120000 index 0000000..8a16ccc --- /dev/null +++ b/content/images/eclipse-20220515-234126.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/jP/q9/SHA512-s62280--e38d6442ee33be62ca39f1d0976888d1b8dde77fb84043133887190e25febd2dcc7f1c0351880d5879ab542b9db3854e172be60cad1208a859e30c30e1f774dc/SHA512-s62280--e38d6442ee33be62ca39f1d0976888d1b8dde77fb84043133887190e25febd2dcc7f1c0351880d5879ab542b9db3854e172be60cad1208a859e30c30e1f774dc \ No newline at end of file diff --git a/content/images/eclipse-20220515-234126.yaml b/content/images/eclipse-20220515-234126.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-234126.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-234942.jpg b/content/images/eclipse-20220515-234942.jpg new file mode 120000 index 0000000..1dd3e25 --- /dev/null +++ b/content/images/eclipse-20220515-234942.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/xv/81/SHA512-s75054--65490d25c866e5b275a84133da3305a2df5b31a5a5a83741ee6149d480c2fa1b446cde857487709b34bb7091f31de734b7bdc225250494f8b1ecdd1934957be2/SHA512-s75054--65490d25c866e5b275a84133da3305a2df5b31a5a5a83741ee6149d480c2fa1b446cde857487709b34bb7091f31de734b7bdc225250494f8b1ecdd1934957be2 \ No newline at end of file diff --git a/content/images/eclipse-20220515-234942.yaml b/content/images/eclipse-20220515-234942.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-234942.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220515-235136.jpg b/content/images/eclipse-20220515-235136.jpg new file mode 120000 index 0000000..40f0ebb --- /dev/null +++ b/content/images/eclipse-20220515-235136.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/0m/kX/SHA512-s74615--1af33e462be8dcc467fb5a81400438974197918af7caa39eea77113c6e49788df04585ea574efca75699d9a79d0f1f1623d4976c17b8129dbcb6a43a4ba84685/SHA512-s74615--1af33e462be8dcc467fb5a81400438974197918af7caa39eea77113c6e49788df04585ea574efca75699d9a79d0f1f1623d4976c17b8129dbcb6a43a4ba84685 \ No newline at end of file diff --git a/content/images/eclipse-20220515-235136.yaml b/content/images/eclipse-20220515-235136.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220515-235136.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20220516-000739.jpg b/content/images/eclipse-20220516-000739.jpg new file mode 120000 index 0000000..fc0b549 --- /dev/null +++ b/content/images/eclipse-20220516-000739.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/jW/6f/SHA512-s68109--7e627c88851979ffa02c55369993935c70d7a9e107ddbf334189825c87436a4fbc1d14249ffbc5f9f9b97acf752c27abe557d11b3f5bf385c62b22eee36b18b6/SHA512-s68109--7e627c88851979ffa02c55369993935c70d7a9e107ddbf334189825c87436a4fbc1d14249ffbc5f9f9b97acf752c27abe557d11b3f5bf385c62b22eee36b18b6 \ No newline at end of file diff --git a/content/images/eclipse-20220516-000739.yaml b/content/images/eclipse-20220516-000739.yaml new file mode 100644 index 0000000..6752422 --- /dev/null +++ b/content/images/eclipse-20220516-000739.yaml @@ -0,0 +1,4 @@ +--- +title: 2022-05-15/16 Lunar Eclipse from Ottawa +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20240408-143755.jpg b/content/images/eclipse-20240408-143755.jpg new file mode 120000 index 0000000..36f5d3c --- /dev/null +++ b/content/images/eclipse-20240408-143755.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/zX/Px/SHA512-s389810--6d85094e85dbfcc4e73a7861d7992ab8d89d31f369ecc6d977ed89f646a96344dc9361374f8f08ba91f426acf9fdf53bfaad89f3f66563822cfc852b93f4cdef/SHA512-s389810--6d85094e85dbfcc4e73a7861d7992ab8d89d31f369ecc6d977ed89f646a96344dc9361374f8f08ba91f426acf9fdf53bfaad89f3f66563822cfc852b93f4cdef \ No newline at end of file diff --git a/content/images/eclipse-20240408-143755.yaml b/content/images/eclipse-20240408-143755.yaml new file mode 100644 index 0000000..7eb4d34 --- /dev/null +++ b/content/images/eclipse-20240408-143755.yaml @@ -0,0 +1,4 @@ +--- +title: 2024-04-08 Solar Eclipse near Cornwall, ON +copyright: 2024 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20240408-151623.jpg b/content/images/eclipse-20240408-151623.jpg new file mode 120000 index 0000000..5b3949f --- /dev/null +++ b/content/images/eclipse-20240408-151623.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/7V/zg/SHA512-s302673--ee3080ea9d00aed29a5af1d407e7dfad733a63131a907cb2d52c7b4342a552bf1b2ad9fa4bd062b96d3355162e09220c14134180091db3d3c9fca5b2f2da464a/SHA512-s302673--ee3080ea9d00aed29a5af1d407e7dfad733a63131a907cb2d52c7b4342a552bf1b2ad9fa4bd062b96d3355162e09220c14134180091db3d3c9fca5b2f2da464a \ No newline at end of file diff --git a/content/images/eclipse-20240408-151623.yaml b/content/images/eclipse-20240408-151623.yaml new file mode 100644 index 0000000..7eb4d34 --- /dev/null +++ b/content/images/eclipse-20240408-151623.yaml @@ -0,0 +1,4 @@ +--- +title: 2024-04-08 Solar Eclipse near Cornwall, ON +copyright: 2024 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20240408-152435.jpg b/content/images/eclipse-20240408-152435.jpg new file mode 120000 index 0000000..5abb405 --- /dev/null +++ b/content/images/eclipse-20240408-152435.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/v5/gQ/SHA512-s273018--1a0d88d6b0756be9b23771154e7062da73c442e3f9f8222a6097b8c079382effe64fd7db6f0f763968d983aa9dada88be56932ebee68cbb59e01523ef483662f/SHA512-s273018--1a0d88d6b0756be9b23771154e7062da73c442e3f9f8222a6097b8c079382effe64fd7db6f0f763968d983aa9dada88be56932ebee68cbb59e01523ef483662f \ No newline at end of file diff --git a/content/images/eclipse-20240408-152435.yaml b/content/images/eclipse-20240408-152435.yaml new file mode 100644 index 0000000..7eb4d34 --- /dev/null +++ b/content/images/eclipse-20240408-152435.yaml @@ -0,0 +1,4 @@ +--- +title: 2024-04-08 Solar Eclipse near Cornwall, ON +copyright: 2024 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/eclipse-20240408-152639.jpg b/content/images/eclipse-20240408-152639.jpg new file mode 120000 index 0000000..21e8d49 --- /dev/null +++ b/content/images/eclipse-20240408-152639.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/wf/58/SHA512-s348783--191e38f10a9f3d6c3e2334795e342b6ea92ba37e28502e102bf3034aae65e0c8bd9fdd8af9847e33e54059f4bcb6f6597394e1e76ff27403b4d606375735e62f/SHA512-s348783--191e38f10a9f3d6c3e2334795e342b6ea92ba37e28502e102bf3034aae65e0c8bd9fdd8af9847e33e54059f4bcb6f6597394e1e76ff27403b4d606375735e62f \ No newline at end of file diff --git a/content/images/eclipse-20240408-152639.yaml b/content/images/eclipse-20240408-152639.yaml new file mode 100644 index 0000000..d162875 --- /dev/null +++ b/content/images/eclipse-20240408-152639.yaml @@ -0,0 +1,7 @@ +--- +title: 2024-04-08 Total Solar Eclipse near Cornwall, ON +copyright: 2024 Nick Bowler +license: cc-by-sa-4.0 +description: | + The Sun's corona is visible during totality. The red spots on the fringes + are likely solar prominences. diff --git a/content/images/eclipse-20240408-152802.jpg b/content/images/eclipse-20240408-152802.jpg new file mode 120000 index 0000000..1eafa28 --- /dev/null +++ b/content/images/eclipse-20240408-152802.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/34/ZV/SHA512-s520397--1fb51e2946228e45bffa5b8552ad9243a52e8ba6fb8715a3885c602d0046a84724795717b4674753bf202dceefa2bee263a853909222217405889b5258db14d8/SHA512-s520397--1fb51e2946228e45bffa5b8552ad9243a52e8ba6fb8715a3885c602d0046a84724795717b4674753bf202dceefa2bee263a853909222217405889b5258db14d8 \ No newline at end of file diff --git a/content/images/eclipse-20240408-152802.yaml b/content/images/eclipse-20240408-152802.yaml new file mode 100644 index 0000000..bc26d22 --- /dev/null +++ b/content/images/eclipse-20240408-152802.yaml @@ -0,0 +1,7 @@ +--- +title: 2024-04-08 Diamond Ring near Cornwall, ON +copyright: 2024 Nick Bowler +license: cc-by-sa-4.0 +description: | + The sun's disc peeks out again at third contact producing the diamond ring + effect. diff --git a/content/images/eclipse-20240408-152846.jpg b/content/images/eclipse-20240408-152846.jpg new file mode 120000 index 0000000..f49afd2 --- /dev/null +++ b/content/images/eclipse-20240408-152846.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/W3/KV/SHA512-s295663--d941929c012be29bbb82e9c22b69280a64b7e9e21321cc7faf2e65088eb251deed5aa2a16b6820473fba40a1057dc72d6b3444e3b916691e8d68322b8d9e1201/SHA512-s295663--d941929c012be29bbb82e9c22b69280a64b7e9e21321cc7faf2e65088eb251deed5aa2a16b6820473fba40a1057dc72d6b3444e3b916691e8d68322b8d9e1201 \ No newline at end of file diff --git a/content/images/eclipse-20240408-152846.yaml b/content/images/eclipse-20240408-152846.yaml new file mode 100644 index 0000000..7eb4d34 --- /dev/null +++ b/content/images/eclipse-20240408-152846.yaml @@ -0,0 +1,4 @@ +--- +title: 2024-04-08 Solar Eclipse near Cornwall, ON +copyright: 2024 Nick Bowler +license: cc-by-sa-4.0 diff --git a/content/images/m48t59y-fixed.jpg b/content/images/m48t59y-fixed.jpg new file mode 120000 index 0000000..d0f066e --- /dev/null +++ b/content/images/m48t59y-fixed.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/wK/GG/SHA512-s215590--23ec4d09ab8ed674c51d1fa81145f4983e207ca989ec65c3035ba49c876aa01c37df3ca458b80ab7863607ec80ec8ac950bd03e7d83ec493adc40fef80c55f8d/SHA512-s215590--23ec4d09ab8ed674c51d1fa81145f4983e207ca989ec65c3035ba49c876aa01c37df3ca458b80ab7863607ec80ec8ac950bd03e7d83ec493adc40fef80c55f8d \ No newline at end of file diff --git a/content/images/m48t59y-fixed.yaml b/content/images/m48t59y-fixed.yaml new file mode 100644 index 0000000..6038682 --- /dev/null +++ b/content/images/m48t59y-fixed.yaml @@ -0,0 +1,6 @@ +--- +title: M48T59Y-70PC1 With Battery Clip +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 +description: | + Finished repair of M48T59Y part with external battery clip glued on top. diff --git a/content/images/m48t59y-installed.jpg b/content/images/m48t59y-installed.jpg new file mode 120000 index 0000000..2fa0639 --- /dev/null +++ b/content/images/m48t59y-installed.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/jF/WK/SHA512-s821129--859631534da810c3a29d2246edf97a8d6a61a2ac67c21e18aee2753eb96a38a2856e45278f44db7a7a0ef9bb1c1ae6b00bc32e72b9b143b5d14a8abc7e376a1d/SHA512-s821129--859631534da810c3a29d2246edf97a8d6a61a2ac67c21e18aee2753eb96a38a2856e45278f44db7a7a0ef9bb1c1ae6b00bc32e72b9b143b5d14a8abc7e376a1d \ No newline at end of file diff --git a/content/images/m48t59y-installed.yaml b/content/images/m48t59y-installed.yaml new file mode 100644 index 0000000..2c74fe6 --- /dev/null +++ b/content/images/m48t59y-installed.yaml @@ -0,0 +1,6 @@ +--- +title: M48T59Y-70PC1 Repair Complete +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 +description: | + Repaired M48T59Y chip installed onto the Sun Ultra 60 motherboard. diff --git a/content/images/m48t59y-solder.jpg b/content/images/m48t59y-solder.jpg new file mode 120000 index 0000000..5d8078e --- /dev/null +++ b/content/images/m48t59y-solder.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/8M/9g/SHA512-s146926--2dd1f0b920387121d4e1f658f151417d55d65dfa27a6b397343deeebde08636236a0e123a9cfa3fdeef8204425c3f7d00a5e5dcee121126535a140a059f6fb04/SHA512-s146926--2dd1f0b920387121d4e1f658f151417d55d65dfa27a6b397343deeebde08636236a0e123a9cfa3fdeef8204425c3f7d00a5e5dcee121126535a140a059f6fb04 \ No newline at end of file diff --git a/content/images/m48t59y-solder.yaml b/content/images/m48t59y-solder.yaml new file mode 100644 index 0000000..dc6253b --- /dev/null +++ b/content/images/m48t59y-solder.yaml @@ -0,0 +1,7 @@ +--- +title: M48T59Y-70PC1 Wire Leads +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 +description: | + M48T59Y with battery leads connected, after disconnecting the internal + battery tabs. diff --git a/content/images/m48t59y-terminals.jpg b/content/images/m48t59y-terminals.jpg new file mode 120000 index 0000000..795475d --- /dev/null +++ b/content/images/m48t59y-terminals.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/98/V1/SHA512-s186948--c3277cf2aea7e159ee6203e9c7f5330f3a1c79a4d2c347c7637c19f354c7cafe2181b54fd40e84eba434a16340fb9cd3a87e76a636d45278846cb46c3d1f606e/SHA512-s186948--c3277cf2aea7e159ee6203e9c7f5330f3a1c79a4d2c347c7637c19f354c7cafe2181b54fd40e84eba434a16340fb9cd3a87e76a636d45278846cb46c3d1f606e \ No newline at end of file diff --git a/content/images/m48t59y-terminals.yaml b/content/images/m48t59y-terminals.yaml new file mode 100644 index 0000000..806df38 --- /dev/null +++ b/content/images/m48t59y-terminals.yaml @@ -0,0 +1,8 @@ +--- +title: M48T59Y-70PC1 Battery Terminals +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 +description: | + M48T59Y with internal battery connections exposed. The negative connection + is on the left, closest to pin 14. The positive connection is on the right, + closest to pin 16. diff --git a/content/images/m48t59y.jpg b/content/images/m48t59y.jpg new file mode 120000 index 0000000..40e10d3 --- /dev/null +++ b/content/images/m48t59y.jpg @@ -0,0 +1 @@ +../../.git/annex/objects/5f/mJ/SHA512-s141937--ebbd8a2ad4b6d4f1c6d66d9f7ba76685c5281bff3d0fb34f7e00e3016b8422c4935aa9b87caa1c4f8ed9b1b7f727b4f2c97d49991f483317c8248f536c225620/SHA512-s141937--ebbd8a2ad4b6d4f1c6d66d9f7ba76685c5281bff3d0fb34f7e00e3016b8422c4935aa9b87caa1c4f8ed9b1b7f727b4f2c97d49991f483317c8248f536c225620 \ No newline at end of file diff --git a/content/images/m48t59y.yaml b/content/images/m48t59y.yaml new file mode 100644 index 0000000..7258310 --- /dev/null +++ b/content/images/m48t59y.yaml @@ -0,0 +1,9 @@ +--- +title: M48T59Y-70PC1 +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 +description: | +

The NVRAM module + used in my Sun Ultra 60 workstation. This combines a normal memory with a + real-time clock and an internal lithium primary cell to maintain everything. + However, the internal cell is long dead so this chip is dead too.

diff --git a/content/projects.md b/content/projects.md index 90413c9..8db0c42 100644 --- a/content/projects.md +++ b/content/projects.md @@ -4,6 +4,9 @@ copyright: 2019 Nick Bowler license: cc-by-nd-4.0 --- +*[RARP]: Reverse Address Resolution Protocol +*[ARP]: Address Resolution Protocol + Most of the operations here in the workshop are tracked on our local [git server](//git.draconx.ca) which can be browsed online. All the work here is [free as in freedom](//www.gnu.org/philosophy/free-sw) which means you are diff --git a/content/projects/cdecl99.md b/content/projects/cdecl99.md index c8ef5ba..c2fb9f4 100644 --- a/content/projects/cdecl99.md +++ b/content/projects/cdecl99.md @@ -1,9 +1,9 @@ --- title: Cdecl99 -copyright: 2021 Nick Bowler +copyright: 2021-2024 Nick Bowler license: gpl-3 or (at your option) any later version module: cdecl99 -release: v1.1 +release: v1.3 --- <%= project_readme %> diff --git a/content/projects/rarpd-dx.md b/content/projects/rarpd-dx.md new file mode 100644 index 0000000..9eaf368 --- /dev/null +++ b/content/projects/rarpd-dx.md @@ -0,0 +1,13 @@ +--- +title: RARP Daemon +copyright: 2023 Nick Bowler +license: gpl-2 or (at your option) any later version +module: rarpd-dx +release: v1 +--- + +*[RARP]: Reverse Address Resolution Protocol +*[ARP]: Address Resolution Protocol + +<%= project_readme %> + diff --git a/content/projects/rrace.md b/content/projects/rrace.md new file mode 100644 index 0000000..b5a111f --- /dev/null +++ b/content/projects/rrace.md @@ -0,0 +1,8 @@ +--- +title: RRace +copyright: 2022 Nick Bowler +license: gpl-3 or (at your option) any later version +module: rrace +--- + +<%= project_readme %> diff --git a/content/projects/slotifier.md b/content/projects/slotifier.md index 26c73d7..b56c130 100644 --- a/content/projects/slotifier.md +++ b/content/projects/slotifier.md @@ -3,7 +3,7 @@ title: Slotifier copyright: 2021 Nick Bowler license: gpl-3 or (at your option) any later version module: slotifier -release: v1.1 +release: v1.2 --- <%= project_readme %> diff --git a/content/pubring.gpg b/content/pubring.gpg new file mode 100644 index 0000000..456deef Binary files /dev/null and b/content/pubring.gpg differ diff --git a/content/style.scss b/content/style.scss index a550ea2..17aff0b 100644 --- a/content/style.scss +++ b/content/style.scss @@ -1,7 +1,7 @@ /*! * Nick's web site: default stylesheet * - * Copyright © 2018-2021 Nick Bowler + * Copyright © 2018-2022 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,42 +17,114 @@ * along with this program. If not, see . */ -// colour definitions -$backgroundcolour: #ffffff; -$foregroundcolour: #000000; +@import "lib/colourmap.scss"; -$linkdefaultcolour: #0000cd; -$linkactivecolour: #ff0000; -$linkvisitedcolour: #800080; +@include defcolours + ( $background: #ffffff #000000 + , $foreground: #000000 #ffffff -$ruledefaultcolour: #d3d3d3; -$rulestrongcolour: #696969; + , $linkdefault: #0000cd #a3aaff + , $linkactive: #ff0000 + , $linkvisited: #800080 #e493f7 + , $focusring: #628cb2 -$annotationcolour: #708090; + , $annotation: #708090 + , $tableshade: #f5f5f5 #101010 -$tableshadecolour: #f5f5f5; + , $ruledefault: #d3d3d3 #494949 + , $rulestrong: #696969 #939393 + ); @mixin header_size($maxwidth, $fontsize) { font-size: $fontsize; max-width: 1em * ($maxwidth / $fontsize); } +html { @include usecolours($background-color: background); } body { - background-color: $backgroundcolour; - color: $foregroundcolour; + @include usecolours($color: foreground); font-family: sans-serif; margin: 1em; } -a:link { color: $linkdefaultcolour; } -a:visited { color: $linkvisitedcolour; } -a:active { color: $linkactivecolour; } +a:link { + @include usecolours($color: linkdefault, $border-color: linkdefault); +} +a:visited { + @include usecolours($color: linkvisited, $border-color: linkvisited); +} +a:active { + @include usecolours($color: linkactive, $border-color: linkactive); +} + +@supports (outline-style: auto) { + a:link { border-width: 0; } + a:focus { @include usecolour(outline, focusring, auto); } + li, td, dt { &>a:link { border: solid 1px transparent; } } +} h1 { @include header_size(60em, 2em); } h2 { @include header_size(60em, 1.5em); } h5 { @include header_size(60em, 1em); } -p>img { max-width: 40em; width: 100%; height: auto; } +h1, h2 { abbr { text-decoration: none; } } + +@supports (display: grid) { + .gallery { + display: grid; + grid-column-gap: 1em; + grid-template-columns: repeat( auto-fill, minmax(18em, 1fr) ); + align-items: center; + + p.img { margin: 0.5em 0; } + } + + @media (max-width: 45em) { + .inline.gallery { + display: block; + p.img { + a { max-width: 24em; } + margin: 1em 0; + } + } + } +} + +p.img { + text-align: center; + + img { + vertical-align: bottom; + max-width: 40em; + width: 100%; + height: auto; + } + + a { + text-decoration: none; + display: inline-block; + border: solid 2px; + } + + a.left { margin: 0 1em 0.5em 0; float: left; clear: left; } + a.right { margin: 0 0 0.5em 1em; float: right; clear: right; } + a.left, a.right { + @media (max-width: 45em) { float: none; margin: 0; } + + max-width: 24em; + } + + small { + @include usecolours($color: foreground); + @media (max-width: 24em) { text-align: left; } + padding: 0.5ex; + display: block; + display: -moz-inline-box; + display: inline-block; + text-align: justify; + font-size: 0.9em; + } +} p, dt, dd, li { text-align: justify; @@ -80,17 +152,19 @@ hr { clear: both; margin: 0.5em 0; border: 0; - border-top: 1px solid $ruledefaultcolour; + @include usecolour(border-top, ruledefault, 1px solid); } kbd { font-family: monospace; font-size: 0.95em; &:before { content: "% "; } + &.ok:before { content: "ok "; } &>span { white-space: nowrap; } blockquote & { display: block; + & + br { display: none; } text-align: left; padding-left: 3em; text-indent: -3em; @@ -98,17 +172,19 @@ kbd { } .permalink { + @include usecolours($color: annotation); font-size: small; - color: $annotationcolour; a:link, a:visited { color: inherit; } + a:active { @include usecolours($color: linkactive); } @media not screen { visibility: hidden; } } // General table styles. table { - border: 1px solid $ruledefaultcolour; + @include usecolour(border-top, ruledefault, 1px solid); border-collapse: collapse; + clear: both; width: 100%; } @@ -128,18 +204,20 @@ td, th { margin: 0; } -thead>tr, tbody>tr { border: solid $ruledefaultcolour; } -th, thead>tr { border-bottom: 1px solid $rulestrongcolour; } -tbody+tbody { border-bottom: 1px solid $ruledefaultcolour; } +thead>tr, tbody>tr { @include usecolour(border, ruledefault, solid); } +th, thead>tr { @include usecolour(border-bottom, rulestrong, 1px solid); } +tbody+tbody { @include usecolour(border-bottom, ruledefault, 1px solid); } *>table, *>th { border: none; } thead>tr { border-width: 1px; } tbody>tr { border-width: 0 1px; } -td + td { box-shadow: -1px 0 $backgroundcolour; } +td + td { + @include usecolour(box-shadow, background, -1px 0); +} tbody>tr { - &:nth-of-type(even) { background-color: $tableshadecolour; } - &:last-child { border-bottom: solid 1px $ruledefaultcolour; } + &:nth-of-type(even) { @include usecolours($background-color: tableshade); } + &:last-child { @include usecolour(border-bottom, ruledefault, solid 1px); } } // Specific table styles @@ -150,8 +228,8 @@ table.cc { } } -// CSS rules for stortable clicky table headers: Update the display of -// the /table based on the current state. Each column has its own set +// CSS rules for sortable clicky table headers: Update the display of +// the table based on the current state. Each column has its own set // nearly-identical rules, only the class names differ. // // The clickytables.xsl stylesheet generates two inputs for each column. @@ -240,10 +318,6 @@ $clickynames: name, date, size; } } - &:focus ~ table th.clicky-#{$col}>label~label>span:first-child { - border-color: $foregroundcolour; - } - // Unhide to allow keyboard navigation display: block !important; pointer-events: none; @@ -264,15 +338,22 @@ $clickynames: name, date, size; } } - &:focus ~ table th.clicky-#{$col}>label~label .svg { - border-color: $foregroundcolour; - } - pointer-events: none; position: absolute; opacity: 0; z-index: -2; } + + $focuslabel: ":focus ~ table th.clicky-#{$col}>label~label"; + #{"input.clicky-#{$col+$focuslabel}"}>span:first-child + , #{"input.clicky-#{$col}-rev#{$focuslabel}"} .svg + { + @include usecolours($border-color: foreground); + @at-root { @supports (outline-style: auto) { & { + @include usecolour(outline, focusring, auto); + border-color: transparent !important; + }}} + } } thead.clicky label { @@ -294,9 +375,13 @@ thead.clicky label { padding-right: 2px; } - &:active { color: $linkactivecolour; } + &:active { @include usecolours($color: linkactive); } &:first-child:active>span, &~label:active>.svg { - border-color: $linkactivecolour; + @include usecolours($border-color: linkactive); + @at-root { @supports (outline-style: auto) { & { + @include usecolour(outline, focusring, auto); + border-color: transparent; + }}} } .svg { @@ -364,7 +449,7 @@ table.filelist { } } -#footer p { color: $annotationcolour; } +#footer p { @include usecolours($color: annotation); } #article-info p { font-style: italic; } .wbr:after { content: "\200b"; } @@ -390,3 +475,25 @@ ul.ordered > { #sitetitle * { float: none; } #footer { padding: 0 1em; } } + +// lighten icon shadows in dark mode +@media (prefers-color-scheme: dark) { + svg.icons { path.shadow, g.shadow>* { opacity: 0.7; } } + svg.icons .shadow>stop { stop-color: #aaa; } + svg.return path.shadow { opacity: 0.45; } +} + +// page-specific dark mode styles +@media (prefers-color-scheme: dark) and (min-width: 35em) { + #page_weblog_responsive_tables { + @each $tN in t6 t7 t8 { + ##{$tN}>tbody>tr.#{$tN}-split { + @include usecolour_dark_(border-bottom, ruledefault); + + &:nth-of-type(odd) ~ tr:nth-of-type(odd) { + @include usecolour_dark_(background-color, tableshade); + } + } + } + } +} diff --git a/content/weblog/eclipse-20210610.md b/content/weblog/eclipse-20210610.md new file mode 100644 index 0000000..96b793f --- /dev/null +++ b/content/weblog/eclipse-20210610.md @@ -0,0 +1,26 @@ +--- +title: Solar Eclipse in Ottawa on 2021-06-10 +copyright: 2021 Nick Bowler +license: cc-by-sa-4.0 +published: 2021-06-13T23:43:47-0400 +--- + +On June 10, 2021, I tried to take some photos of the sun, but the moon +kept getting in the way. + +<%= gallery_img(@items["/images/eclipse-20210610-sunrise.jpg"], caption: < +<%= gallery_img(@items["/images/eclipse-20210610-max.jpg"], caption: < +<%= gallery_img(@items["/images/eclipse-20210610-clouds.jpg"], caption: < +<%= gallery_img(@items["/images/eclipse-20210610-farewell.jpg"], caption: < diff --git a/content/weblog/eclipse-20220515.md b/content/weblog/eclipse-20220515.md new file mode 100644 index 0000000..ab471b7 --- /dev/null +++ b/content/weblog/eclipse-20220515.md @@ -0,0 +1,11 @@ +--- +title: Lunar Eclipse in Ottawa on 2022-05-15 +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 +published: 2022-05-16T01:17:29-0400 +--- + +<% images = @items.find_all("/images/eclipse-202205*.jpg") +images.sort_by(&:identifier).each do |item| %> +<%= gallery_img(item, caption: "") %> +<% end %> diff --git a/content/weblog/eclipse-20240408.md b/content/weblog/eclipse-20240408.md new file mode 100644 index 0000000..0cf01bf --- /dev/null +++ b/content/weblog/eclipse-20240408.md @@ -0,0 +1,14 @@ +--- +title: Solar Eclipse near Cornwall on 2024-04-08 +copyright: 2024 Nick Bowler +license: cc-by-sa-4.0 +published: 2024-04-09T00:44:23-0400 +updated: 2024-04-09T21:04:19-0400 +--- + +More to come... + +<% images = @items.find_all("/images/eclipse-20240408*.jpg") +images.sort_by(&:identifier).each do |item| %> +<%= gallery_img(item, caption: "") %> +<% end %> diff --git a/content/weblog/responsive-tables.md b/content/weblog/responsive-tables.md index 2063484..a668e16 100644 --- a/content/weblog/responsive-tables.md +++ b/content/weblog/responsive-tables.md @@ -272,12 +272,12 @@ are pretty easy to fix in the stylesheet. #t6>thead, #t6>tbody { display: grid; } #t6>tbody>tr.t6-split { border-bottom: 1px solid <%= - scss_get_var(:ruledefaultcolour) %>; } + scss_get_colour(:ruledefault) %>; } #t6>tbody>tr.t6-split:nth-of-type(odd) ~ tr:nth-of-type(even) { background-color: initial; } #t6>tbody>tr.t6-split:nth-of-type(odd) ~ tr:nth-of-type(odd) { - background-color: <%= scss_get_var(:tableshadecolour) %>; + background-color: <%= scss_get_colour(:tableshade) %>; } } } @@ -325,12 +325,12 @@ these techniques to [table 1](#t1). #t7>thead, #t7>tbody { display: grid; } #t7>tbody>tr.t7-split { border-bottom: 1px solid <%= - scss_get_var(:ruledefaultcolour) %>; } + scss_get_colour(:ruledefault) %>; } #t7>tbody>tr.t7-split:nth-of-type(odd) ~ tr:nth-of-type(even) { background-color: initial; } #t7>tbody>tr.t7-split:nth-of-type(odd) ~ tr:nth-of-type(odd) { - background-color: <%= scss_get_var(:tableshadecolour) %>; + background-color: <%= scss_get_colour(:tableshade) %>; } } } @@ -386,12 +386,12 @@ in a stylesheet. We will do it with more grids. #t8>thead, #t8>tbody { display: grid; } #t8>tbody>tr.t8-split { border-bottom: 1px solid <%= - scss_get_var(:ruledefaultcolour) %>; } + scss_get_colour(:ruledefault) %>; } #t8>tbody>tr.t8-split:nth-of-type(odd) ~ tr:nth-of-type(even) { background-color: initial; } #t8>tbody>tr.t8-split:nth-of-type(odd) ~ tr:nth-of-type(odd) { - background-color: <%= scss_get_var(:tableshadecolour) %>; + background-color: <%= scss_get_colour(:tableshade) %>; } } diff --git a/content/weblog/ultra60-nvram.md b/content/weblog/ultra60-nvram.md new file mode 100644 index 0000000..ec96370 --- /dev/null +++ b/content/weblog/ultra60-nvram.md @@ -0,0 +1,101 @@ +--- +title: M48T59Y-70PC1 NVRAM Battery Replacement +copyright: 2022 Nick Bowler +license: cc-by-sa-4.0 +published: 2022-07-09T12:12:21-0400 +--- + +*[NVRAM]: Non-Volatile Random Access Memory +*[SRAM]: Static Random-Access Memory +*[NOS]: New Old Stock +*[DIP]: Dual In-line Package +*[SOIC]: Small-Outline Integrated Circuit +*[MAC]: Media Access Control + +Thanks to [Mark Henderson's Sun NVRAM FAQ][nvram-faq] for providing invaluable +insight regarding this repair. +{:article-info="article-info"} + +[nvram-faq]: http://web.archive.org/web/20150919135835/http://www.squirrel.com/sun-nvram-hostid.faq.html + +The Sun Ultra 60 workstation uses an ST M48T59Y-70PC1 battery-backed SRAM with +real-time clock. When the embedded lithium primary cell inevitably dies, the +chip is essentially useless. The most noticeable negative effect of a dead +chip is that the workstation always powers up in a default configuration with +diag-switch? true, running several minutes of self tests every time, with +bogus MAC and host ID values. + +<%= floating_img(@items["/images/m48t59y.jpg"], caption: < + +This device was branded obsolescent by the manufacturer in April of 2008 and +has presumably been out of production since around that time. Similar chips +like the M48T58Y are still made but they are expensive (around $40) and slight +differences may result in compatibility problems. It appears that NOS parts +can be found fairly cheap online but these must be almost 15 years old by now +and who knows what state the embedded batteries are in. No thanks. + +One option could be to find the SOIC version of the M48T59Y for which NOS also +seems to be available, although somewhat less readily than the DIP modules, and +then construct an adapter board to fit into the DIP socket on the motherboard. +The SOIC package does not include the battery and crystal; instead, it has +contacts on the top to attach a separate "SNAPHAT" package which are still +made. This would be complicated and somewhat expensive. + +Fortunately, a straightforward (if time-consuming) repair is possible. This +is a literal hackjob: we can dig through the potting to expose the battery +terminals, disconnect the internal battery, and connect a normal battery clip. +This enables the use of readily-available CR2032 lithium primary cells that can +be replaced as needed, just like a normal PC. Since we already have the chip +we need, it is not necessary to source any obscure or expensive components. + +<%= +floating_img(@items["/images/m48t59y-terminals.jpg"], left: 1, caption: '') +%> + +<%= +floating_img(@items["/images/m48t59y-solder.jpg"], left: 1, caption: '') +%> + +The battery contacts are located on the end opposite pin 1, between pins +14 and 15. Looking underneath the chip there is a small well at either end +filled with potting compound. The battery connections are inside one of +these. Using a knife, cut back the plastic outer shell on the battery side, +then begin scraping away potting compound until the terminals are exposed. +You can use a suitable DIP socket to help protect the pins from accidental +damage. + +Once the terminals are exposed, the internal battery must be disconnected. +The thick protruding tabs near the bottom of the module are what we want +to solder to. The vertical strips going up and into the module are the +internal battery terminals. These can be desoldered from the tabs and +lifted out of the way, or simply cut off. + +With the time-consuming parts completed it is a straightforward matter to +connect a normal battery clip to the exposed terminals. As the Ultra 60 has +no clearance issues I simply glued it to the top of the chip. Since this +would obscure the barcode sticker which is useful to restore the original MAC +address and host ID, I moved this sticker to the side of the chip. + +Finally all that remains is to put everything back together and power up +the system. The system will run the full self-diagnostic tests again and +if all goes well, the "NVRAM Battery Detect Test" should no longer display +any errors. At the ok prompt, the memory can now be initialized. Where +"AA BB CC" are the six hexadecimal digits from the orange barcode sticker: + +set-defaults
+setenv diag-switch? false
+8 0 20 AA BB CC AABBCC mkpl
<Ctrl-D><Ctrl-R>

+.idprom
+reset + +<%= gallery_img(@items["/images/m48t59y-fixed.jpg"], caption: < +<%= gallery_img(@items["/images/m48t59y-installed.jpg"], caption: < diff --git a/gitmodules/cdecl99 b/gitmodules/cdecl99 index 6cc7c1a..db974c0 160000 --- a/gitmodules/cdecl99 +++ b/gitmodules/cdecl99 @@ -1 +1 @@ -Subproject commit 6cc7c1ad6a714b7ea8ae1445e502ec7ce4ecf4ab +Subproject commit db974c0a690f2044dcbc06446333837c3c3e1cec diff --git a/gitmodules/rarpd-dx b/gitmodules/rarpd-dx new file mode 160000 index 0000000..e560983 --- /dev/null +++ b/gitmodules/rarpd-dx @@ -0,0 +1 @@ +Subproject commit e5609838c7733c84200f368bfd89bf2fe07b3d9e diff --git a/gitmodules/rrace b/gitmodules/rrace new file mode 160000 index 0000000..c1dbd8f --- /dev/null +++ b/gitmodules/rrace @@ -0,0 +1 @@ +Subproject commit c1dbd8fcf932d82b4d77da62288b4a6cdf5c1470 diff --git a/layouts/copyright.xml b/layouts/copyright.xml new file mode 100644 index 0000000..a3153bb --- /dev/null +++ b/layouts/copyright.xml @@ -0,0 +1,29 @@ +<% +s = ' ' * (@indent || 2) +copyyears = {} +copyauthors = {} +[@item.fetch(:copyright, [])].flatten.each do |copyright| %> +<%=s%><%= copyright %><% +x = expand_copyright(copyright) +x[:years].each do |y| copyyears[y] = 1 end +copyauthors[x[:name]] = 1 +end +copyyears.keys.sort.each do |y| %> +<%=s%><%= y %><% +end +copyauthors.keys.sort.each do |i| %> +<%=s%><%= i %><% +end + if @item[:license] then + licref = @item[:license].split + lic = find_license(licref[0]) %> +<%=s%> +<%=s%> <%= File::basename(lic.identifier.without_ext) %> +<%=s%> <%= license_shortname(lic) %> +<%=s%> <%= [lic[:title], licref[1..-1]].compact.join(" ").strip %> +<%=s%> <%= item_uri(lic) %> +<%=s%> <%= + lic[:"modification-allowed"] == true ? "yes" : "no" + %> +<%=s%><% +end %> diff --git a/layouts/default.xml b/layouts/default.xml index 949290a..2f78b3d 100644 --- a/layouts/default.xml +++ b/layouts/default.xml @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - +
@@ -255,8 +209,15 @@ +

- Copying and distribution of this material + + + Except as otherwise noted, copying + + Copying + + and distribution of this material , with or without modification, @@ -321,10 +282,6 @@ - + + + - + +

-

- Posted - -

+ + +
+ +

+ Posted + + + + , last updated + + + +

+
+ + + + + + + + + + + + + + + + + img + + + + + + + + + + + + + +
+ + gallery + + inline + + + + + +
+
+ + + +
+
+ + <xsl:variable name='page-title' select='string(/document/title)' /> @@ -444,12 +475,17 @@ <div id='footer'> <xsl:apply-templates select='/document/copyright' /> <xsl:apply-templates select='/document/license' /> + <xsl:if test='/document/image[copyright != /document/copyright + or license/identifier != /document/license/identifier]'> + <xsl:call-template name='image-attribution' /> + </xsl:if> <xsl:apply-templates select='/document/source' /> </div> </body> </html> </xsl:template> +<xsl:include href='layouts/whitespace.xsl' /> <xsl:include href='layouts/clickytable.xsl' /> </xsl:stylesheet> diff --git a/layouts/embed-svg.xsl b/layouts/embed-svg.xsl index 2b3f8e2..0aee04d 100644 --- a/layouts/embed-svg.xsl +++ b/layouts/embed-svg.xsl @@ -2,7 +2,7 @@ <!-- Nick's web site: SVG embedding. - Copyright © 2021 Nick Bowler + Copyright © 2021-2022 Nick Bowler This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -110,7 +110,23 @@ <xsl:value-of select='concat("es-", generate-id($idnode))' /> </xsl:attribute> </xsl:if> - <xsl:apply-templates mode='embed-svg' select='@*[local-name()!="id"]' /> + <xsl:choose> + <xsl:when test='$idnode/@src and not(parent::*)'> + <!-- remove .svg suffix --> + <xsl:variable name='raw' + select='substring($idnode/@src, 1, string-length($idnode/@src)-4)' /> + + <xsl:attribute name='class'> + <xsl:value-of select='normalize-space(concat(@class, " embed ", + translate($raw, "/", " ")))' /> + </xsl:attribute> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates mode='embed-svg' select='@class' /> + </xsl:otherwise> + </xsl:if> + <xsl:apply-templates mode='embed-svg' + select='@*[local-name()!="id" and local-name()!="class"]' /> <xsl:apply-templates mode='embed-svg' select='node()'> <xsl:sort select='-count(self::svg:metadata)' data-type='number' /> </xsl:apply-templates> diff --git a/layouts/functions.xsl b/layouts/functions.xsl index a88c338..bbaf90e 100644 --- a/layouts/functions.xsl +++ b/layouts/functions.xsl @@ -1,7 +1,7 @@ <!-- Nick's web site: XSLT helper functions. - Copyright © 2019-2021 Nick Bowler + Copyright © 2019-2022 Nick Bowler This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -162,4 +162,18 @@ </func:result> </func:function> +<!-- + f:contains-token(list, token) + Returns true iff the space-separated list contains the given token +--> +<func:function name='f:contains-token'> + <xsl:param name='haystack' /> + <xsl:param name='needle' /> + + <func:result select='contains( + concat(" ", normalize-space($haystack), " "), + concat(" ", normalize-space($needle), " ") + )' /> +</func:function> + </xsl:stylesheet> diff --git a/layouts/imginfo.xsl b/layouts/imginfo.xsl index 7859d8b..e39c07d 100644 --- a/layouts/imginfo.xsl +++ b/layouts/imginfo.xsl @@ -30,7 +30,7 @@ <xsl:copy><xsl:apply-templates select='node()|@*' /></xsl:copy> </xsl:template> -<xsl:template name='exif'> +<xsl:template name='exif' mode='exif' match='*'> <xsl:param name='node' select='.' /> <xsl:param name='name' select='local-name($node)' /> @@ -39,6 +39,7 @@ <td><xsl:value-of select='$node' /></td> </tr> </xsl:template> + <xsl:template match='exif'> <h2>Metadata</h2> <table> @@ -46,50 +47,42 @@ <tr><th>Attribute</th><th>Value</th></tr> </thead> <tbody> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='make' /> + <xsl:apply-templates select='make' mode='exif'> <xsl:with-param name='name' select='"Camera make"' /> - </xsl:call-template> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='model' /> + </xsl:apply-templates> + <xsl:apply-templates select='model' mode='exif'> <xsl:with-param name='name' select='"Camera model"' /> - </xsl:call-template> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='date_time_original' /> + </xsl:apply-templates> + <xsl:apply-templates select='date_time_original' mode='exif'> <xsl:with-param name='name' select='"Date taken"' /> - </xsl:call-template> - <xsl:call-template name='exif'> + </xsl:apply-templates> + <xsl:apply-templates select='exposure_time' mode='exif'> <xsl:with-param name='node' select='concat(exposure_time, "s")' /> <xsl:with-param name='name' select='"Shutter speed"' /> - </xsl:call-template> - <xsl:call-template name='exif'> + </xsl:apply-templates> + <xsl:apply-templates select='f_number' mode='exif'> <xsl:with-param name='node' select='concat("f/", f_number)' /> <xsl:with-param name='name' select='"Aperture"' /> - </xsl:call-template> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='exposure_bias_value' /> + </xsl:apply-templates> + <xsl:apply-templates select='exposure_bias_value' mode='exif'> <xsl:with-param name='name' select='"Exposure compensation"' /> - </xsl:call-template> - <xsl:call-template name='exif'> + </xsl:apply-templates> + <xsl:apply-templates select='focal_length' mode='exif'> <xsl:with-param name='node' select='concat(focal_length, "mm")' /> <xsl:with-param name='name' select='"Focal length"' /> - </xsl:call-template> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='flash' /> + </xsl:apply-templates> + <xsl:apply-templates select='flash' mode='exif'> <xsl:with-param name='name' select='"Flash"' /> - </xsl:call-template> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='iso_speed_ratings' /> + </xsl:apply-templates> + <xsl:apply-templates select='iso_speed_ratings' mode='exif'> <xsl:with-param name='name' select='"ISO speed rating"' /> - </xsl:call-template> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='exposure_program' /> + </xsl:apply-templates> + <xsl:apply-templates select='exposure_program' mode='exif'> <xsl:with-param name='name' select='"Exposure program"' /> - </xsl:call-template> - <xsl:call-template name='exif'> - <xsl:with-param name='node' select='metering_mode' /> + </xsl:apply-templates> + <xsl:apply-templates select='metering_mode' mode='exif'> <xsl:with-param name='name' select='"Metering mode"' /> - </xsl:call-template> + </xsl:apply-templates> </tbody> </table> </xsl:template> diff --git a/layouts/whitespace.xsl b/layouts/whitespace.xsl new file mode 100644 index 0000000..c15639a --- /dev/null +++ b/layouts/whitespace.xsl @@ -0,0 +1,116 @@ +<!-- + Nick's web site: white-space normalization for Nokogiri. + + Copyright © 2019, 2022 Nick Bowler + + Nokogiri's pretty-printer seems a bit weird. Regardless of the indentation + setting, if an element has no child text nodes then it will be pretty- + printed. This works by adding arbitrary whitespace to that element, and + then all of its children are eligible to be pretty-printed. + + If an element has any text nodes at all, then it is not pretty-printed and + neither are any of its descendents. + + In general, adding or removing whitespace from an XHTML document is unsafe + (changes the meaning) around span-level elements, but it is OK around other + kinds of elements. + + These templates exploit the Nokogiri behaviour in two ways: + + - by explicitly stripping whitespace wherever it is safe to do so, attempting + to allow pretty printing as much as possible without changing the meaning + of the document. + + - by explicitly adding text nodes to suppress pretty printing in + situations where it would otherwise change the meaning of the document. + + The text nodes which are added consist of U+2060 word joiner characters. + These should be removed from the final document in a separate pass. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/> +--> +<xsl:stylesheet version='1.0' + xmlns='http://www.w3.org/1999/xhtml' + xmlns:xhtml='http://www.w3.org/1999/xhtml' + xmlns:xsl='http://www.w3.org/1999/XSL/Transform' + xmlns:f='http://draconx.ca/my-functions'> + +<xsl:import href='functions.xsl' /> + +<!-- + Adding arbitrary whitespace to <pre> is bad, so we inject zero-width non- + breaking spaces to prevent this. This will render fine but the spaces + should be removed before final output to avoid problems with copy+paste. +--> +<xsl:template match='xhtml:pre'> + <xsl:copy> + <xsl:apply-templates select='node()|@*' /> + <xsl:text>⁠</xsl:text> + </xsl:copy> +</xsl:template> + +<!-- + Likewise, adding spaces between consecutive span-level elements where + none existed before won't go over well. +--> +<xsl:template name='glue-preceding-span'> + <xsl:if test='f:element-is-span(preceding-sibling::node()[1])'> + <xsl:text>⁠</xsl:text> + </xsl:if> +</xsl:template> + +<xsl:template match='*[f:element-is-span()]'> + <xsl:call-template name='glue-preceding-span' /> + <xsl:copy> + <xsl:apply-templates select='node()|@*' /> + <xsl:if test='*'> + <!-- avoid breaking within a span element --> + <xsl:text>⁠</xsl:text> + </xsl:if> + </xsl:copy> +</xsl:template> + +<!-- + Manually strip whitespace-only text nodes so the pretty printer can do its + thing on remaining elements. +--> +<xsl:template match='text()[normalize-space(.) = ""]'> + <xsl:choose> + <!-- preserve anything according to xml:space --> + <xsl:when test='ancestor::*[@xml:space][1][@xml:space="preserve"]'> + <xsl:copy /> + </xsl:when> + <!-- preserve anything under <pre> --> + <xsl:when test='ancestor::xhtml:pre'><xsl:copy /></xsl:when> + <!-- preserve whitespace which is the only child node of an element --> + <xsl:when test='count(../node()) = 1'><xsl:copy /></xsl:when> + <!-- preserve whitespace between consecutive span-level elements + which have at least one non-whitespace sibling text element --> + <xsl:when test='f:element-is-span(preceding-sibling::node()[1]) + and f:element-is-span(following-sibling::node()[1]) + and ../text()[normalize-space(.) != ""]'> + <xsl:copy /> + </xsl:when> + </xsl:choose> +</xsl:template> + +<!-- Clean up whitespace where harmless to do so --> +<xsl:template match='xhtml:p/node()[1][self::text()]'> + <xsl:value-of select='f:strip-leading()' /> +</xsl:template> +<xsl:template match='xhtml:p/node()[position()=last()][self::text()]'> + <xsl:value-of select='f:strip-trailing()' /> +</xsl:template> + +</xsl:stylesheet> diff --git a/lib/colourmap.scss b/lib/colourmap.scss new file mode 100644 index 0000000..e4d8d65 --- /dev/null +++ b/lib/colourmap.scss @@ -0,0 +1,113 @@ +// Nick's web site: SCSS colourmap helpers for automatic light/dark styles. +// +// Copyright © 2022 Nick Bowler +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +// database of colour names +$colourmap: (); + +// database of combination CSS properties that should be translated to +// colour-only properties (e.g., border-top -> border-top-color). +$_colourpropmap: + ( border-top: border-top-color + , border-bottom: border-bottom-color + , border-left: border-left-color + , border-right: border-right-color + , border: border-color + ); + +// Define a named set of colours. Pass keyword arguments with each keyword +// being a colour name and the argument is a list of one or two colours. +// +// When two colours are specified, the first should be for "light" backgrounds +// and the second for "dark". +// +// For example: +// +// @include defcolours($bg: white black, $fg: black white); +@mixin defcolours($args...) { + @each $colour, $list in keywords($args) { + $colourmap: map-merge($colourmap, ($colour: $list)) !global; + } +} + +// Obtain the colour value for a previously-defined colour name. By +// default, its primary (light) colour value is returned; this can be +// changed with the $num keyword parameter. +// +// The $pre and $post keyword arguments may be used to supplement the +// result with additional tokens either before or after the colour +// value, respectively, as might be used for combined properties +// such as border, outline, etc. +@function getcolour($colour, $pre: (), $post: (), $num: 1) { + @return join(append($pre, nth(map-get($colourmap, $colour), $num)), $post); +} + +@mixin usecolour_dark_($prop, $colour, $pre: (), $post: ()) { + @if (length(map-get($colourmap, $colour)) > 1) { + $transprop: map-get($_colourpropmap, $prop); + @if $transprop { + #{$transprop}: getcolour($colour, $num: 2) + } @else { + #{$prop}: getcolour($colour, $pre, $post, 2); + } + } +} + +// Sets the given CSS property to the specified colour name. The $pre +// and $post keyword arguments may be used to supplement the property +// value, as with the getcolour function. +// +// For two-value colours, the property is set using CSS variables to +// adapt the colour based on the user's preference for a light or dark +// background. The rules will fall back to the static (light) colour +// if CSS variables are not supported. +// +// For example: +// +// @include usecolour(border, fg, $pre: solid 1px); +@mixin usecolour($prop, $colour, $pre: (), $post: ()) { + #{$prop}: getcolour($colour, $pre, $post); + @at-root { + @media (prefers-color-scheme: dark) { + & { @include usecolour_dark_($prop, $colour, $pre, $post); } + } + } +} + +// Convenience helper to assign multiple colour properties at once, for +// the common case where the $pre and $post arguments to usecolour are +// not required. +// +// Takes any number of keyword arguments with the keyword being the +// property name and the value being the colour name. +// +// For example: +// +// @include usecolours($background-color: bg, $color: fg); +@mixin usecolours($args...) { + @each $prop, $colour in keywords($args) { + #{$prop}: getcolour($colour); + } + @at-root { + @media (prefers-color-scheme: dark) { + & { + @each $prop, $colour in keywords($args) { + @include usecolour_dark_($prop, $colour); + } + } + } + } +} diff --git a/lib/compiledcontent.rb b/lib/compiledcontent.rb new file mode 100644 index 0000000..80e7911 --- /dev/null +++ b/lib/compiledcontent.rb @@ -0,0 +1,25 @@ +# Nick's web site: compiled_content filter. Simply calls the compiled_content +# method on the current item to retrieve the text from a named rep or snapshot. +# +# Copyright © 2022-2023 Nick Bowler +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +class CompiledContentFilter < Nanoc::Filter + identifier :compiled_content + + def run(content, params = {}) + return @item.compiled_content(**params) + end +end diff --git a/lib/css-darkmode.rb b/lib/css-darkmode.rb new file mode 100644 index 0000000..f15f64d --- /dev/null +++ b/lib/css-darkmode.rb @@ -0,0 +1,207 @@ +# Nick's web site: css_darkmode filter. Cut out dark-mode media queries +# from a stylesheet and either re-insert them at the end of the same +# stylesheet, or produce a separate stylesheet for use as an alternate. +# +# Copyright © 2022 Nick Bowler +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +class CssDarkModeFilter < Nanoc::Filter + identifier :css_darkmode + + require 'crass' + + def filter_whitespace(nodes) + return nodes.reject {|x| x[:node] == :whitespace } + end + + # Return a new list of nodes where consecutive whitespace nodes have been + # replaced with a single whitespace node, and if the whitespace contains + # one or more newlines, everything before the final newline is removed. + def simplify_whitespace(nodes) + nodes.slice_when do |a,b| + a[:node] != :whitespace or b[:node] != :whitespace + end.map do |x| + if x[0][:node] == :whitespace + combined = x.map{|y| y[:raw]}.join.sub(/.*\n/m, "\n") + x[0].merge({ raw: combined}) + else + x[0] + end + end + end + + def is_media_dark_block(x) + return false unless x[:node] == :simple_block + + list = filter_whitespace(x[:value]) + list.length == 3 and + list[0][:node] == :ident and + list[0][:value] == "prefers-color-scheme" and + list[1][:node] == :colon and + list[2][:node] == :ident and + list[2][:value] == "dark" + end + + def is_media_dark(x) + return false unless x[:node] == :at_rule and x[:name] == "media" + + x[:prelude].index {|y| is_media_dark_block(y)} + end + + def is_supports_block(x) + true if x[:node] == :at_rule and x[:name] == "supports" + end + + # Remove (prefers-color-scheme: dark) conditions from a media query. + # If the resulting query is empty, returns the query's block alone. + # Otherwise, returns the modified query. + def prune_media_dark(x) + start_index = 0 + end_index = 0 + state = :init + + x[:prelude].each do |y| + case state + when :init + end_index += 1 + if is_media_dark_block(y) + state = :post + elsif y[:node] == :ident and y[:value] == "and" + state = :pre + else + start_index = end_index + state = :init + end + when :pre + end_index += 1 + if is_media_dark_block(y) + state = :post + elsif y[:node] == :whitespace + state = :pre + else + start_index = end_index + state = :init + end + when :post + if y[:node] == :whitespace + end_index += 1 + state = :post + elsif y[:node] == :ident and y[:value] == "and" + end_index += 1 + state = :post + else + break + end + end + end + + x[:prelude].slice!(start_index..end_index-1) + return x[:block] if filter_whitespace(x[:prelude]).empty? + x + end + + def equiv_query(a, b) + return false unless a.class == b.class + + case a + when Array + a = filter_whitespace(a) + b = filter_whitespace(b) + + return false unless a.length == b.length + return a.map.with_index{|x,i| equiv_query(x, b[i])}.all? + when Hash + return false unless a[:node] == b[:node] + case a[:node] + when :at_rule + return equiv_query(a[:prelude], b[:prelude]) + when :simple_block + return equiv_query(a[:value], b[:value]) + else + return (a[:value] == b[:value] and a[:unit] == b[:unit]) + end + end + end + + def process(tree, params) + last_visited = {} + darknodes = [] + + tree.delete_if do |x| + sep = { node: :whitespace, raw: "\n" } + if last_visited[:node] == :whitespace + # Try to maintain indentation + sep[:raw] += last_visited[:raw].sub(/[^\n]*\z|.*\n/m, "") + end + last_visited = x + + if is_supports_block(x) + # Re-parse the block as a list of rules + s = Crass::Parser.stringify(x[:block]) + x[:block] = Crass::Parser.parse_rules(s, params) + + block = process(x[:block], params) + unless block.empty? + block << { node: :whitespace, raw: "\n" } + darknodes << [sep, x.merge({ block: block })] + end + + Crass::Parser.stringify(x[:block]).strip.empty? + elsif is_media_dark(x) + if params[:alternate] + x = prune_media_dark(x) + end + darknodes << [sep, x] + end + end + + # Combine consecutive equivalent media queries into a single query + result = darknodes.slice_when do |a,b| + !equiv_query(a[1], b[1]) + end.each.map do |x| + case x[0][1] + when Hash + g = x.map{ |sep, node| node[:block] }.flatten + [ x[0][0], x[0][1].merge({ block: simplify_whitespace(g) }) ] + else + x + end + end.flatten + + simplify_whitespace(result) + end + + def run(content, params = {}) + params = { + preserve_comments: true, + preserve_hacks: true + }.merge(params) + + tree = Crass.parse(content, params) + + prologue = tree.take_while do |x| + x[:node] == :comment or x[:node] == :whitespace + end + tree.slice!(0, prologue.length) + + output = "#{Crass::Parser.stringify(prologue).rstrip}\n" + darknodes = process(tree, params) + unless params[:alternate] + tree = simplify_whitespace(tree) + output += "#{Crass::Parser.stringify(tree).rstrip}\n" + end + output += "#{Crass::Parser.stringify(darknodes).rstrip}\n" + end +end diff --git a/lib/gpg-wkd.rb b/lib/gpg-wkd.rb new file mode 100644 index 0000000..b2379f1 --- /dev/null +++ b/lib/gpg-wkd.rb @@ -0,0 +1,196 @@ +# Nick's web site: Export GPG public keys for HTTP Keyserver and the +# Web Key Directory +# +# Copyright © 2022 Nick Bowler +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +module WKD + require 'open3' + + @@gpg2 = "/usr/bin/gpg" + @@wksclient = "/usr/libexec/gpg-wks-client" + + def WKD.gpg2; @@gpg2 end + def WKD.gpg2=(x); @@gpg2 = x end + def WKD.wksclient; @@wksclient end + def WKD.wksclient=(x); @@wksclient = x end + + # Convert a list of keyring filenames into GPG keyring arguments + def WKD.keyring_args(args) + return [ "--no-default-keyring", + *args.map { |x| "--keyring=" + (x['/'] ? x : "./" + x) } ] + end + + # Helper for implementing export filters below + def WKD.export(item, id, *args) + data, result = Open3.capture2(@@gpg2, "--export", *args, + *WKD.keyring_args(item[:keyrings]), id.chomp) + raise "gpg failed" unless result.success? + return data + end + + # Return a list of all key fingerprints known from the given GPG keyrings. + def WKD.keys_from_keyrings(*args) + fps = {} + + Open3.popen2(@@gpg2, + "--with-colons", "--list-keys", *WKD.keyring_args(args) + ) do |stdin, stdout, result| + stdin.close + stdout.each do |line| + fields = line.split(":") + next if fields[0] != "fpr" + fps[fields[9]] = true + end + stdout.close + + raise "gpg failed" unless result.value.success? + end + + return fps.keys + end + + # Return a list of all UIDs known from the given GPG keyrings. + def WKD.uids_from_keyrings(*args) + uids = {} + + Open3.popen2(@@gpg2, + "--with-colons", "--list-keys", *WKD.keyring_args(args) + ) do |stdin, stdout, result| + stdin.close + stdout.each do |line| + fields = line.split(":") + next if fields[0] != "uid" + fields[9].gsub!(/\\x../) { |x| x[2..].hex.chr } + uids[fields[9]] = true + end + stdout.close + + raise "gpg failed" unless result.value.success? + end + + return uids.keys + end + + # Given a list of UIDs, return a dictionary where the keys are UIDs + # and the values are the WKS hash. + def WKD.hashes_from_uids(*args) + wkd_hash = {} + + consume_output = Proc.new do |s| + while l = s.slice!(/([^\n]*)\n/) do + hash, uid = l.chomp.split(nil, 2) + wkd_hash[uid] = hash + end + end + + Open3.popen2(@@wksclient, + "--print-wkd-hash" + ) do |stdin, stdout, result| + buf = "" + args.flatten.each do |uid| + stdin.puts(uid) + stdin.flush + + loop do + buf += stdout.read_nonblock(100) + consume_output.call(buf) + rescue EOFError, IO::WaitReadable + break + end + end + stdin.close + + loop do + buf += stdout.readpartial(100) + consume_output.call(buf) + rescue EOFError + break + end + stdout.close + + raise "gpg-wks-client failed" unless result.value.success? + end + + return wkd_hash + end + +end + +# Call during preprocessing to create items for each unique UID found in the +# given keyring items. The items have the identifier /gpg/UID and the content +# is the same UID. The items are created with the :keyrings attribute set to +# the list of keyring files and :wkd_hash is for the Web Key Directory. +def create_wkd_items(keyring_items) + keyring_files = {} + [*keyring_items].each { |item| keyring_files[item.raw_filename] = true } + + wkd = WKD.hashes_from_uids(WKD.uids_from_keyrings(*keyring_files.keys)) + wkd.each do |uid, hash| + attrs = { + keyrings: keyring_files.keys, + wkd_hash: hash + } + @items.create(uid, attrs, "/gpg/" + uid) + end +end + +def create_hkp_items(keyring_items) + keyring_files = {} + [*keyring_items].each { |item| keyring_files[item.raw_filename] = true } + + fps = WKD.keys_from_keyrings(*keyring_files.keys) + keyids_64 = {} + keyids_32 = {} + + fps.each do |fp| + id64 = fp[-16..] + id32 = fp[-8..] + + keyids_64[id64] = keyids_64[id64].to_i + 1 + keyids_32[id32] = keyids_32[id32].to_i + 1 + end + + fps.each do |fp| + id64 = fp[-16..] + id32 = fp[-8..] + + attrs = { keyrings: keyring_files.keys } + attrs[:id64] = id64 if keyids_64[id64] == 1 + attrs[:id32] = id32 if keyids_32[id32] == 1 + + @items.create("0x"+fp, attrs, "/gpg/" + fp) + end +end + +# Convert items created by create_wkd_items into real GPG keyrings. +class WKDExport < Nanoc::Filter + identifier :wkd_export + type :text => :binary + + def run(content, params = {}) + WKD.export(item, content, "--output=" + output_filename) + end +end + +class WKDExportArmor < Nanoc::Filter + identifier :wkd_export_armor + type :text + + def run(content, params = {}) + data = WKD.export(item, content, "--armor") + return data + end +end diff --git a/lib/helpers.rb b/lib/helpers.rb index c9a1cc3..24d37e4 100644 --- a/lib/helpers.rb +++ b/lib/helpers.rb @@ -1,6 +1,6 @@ # Nick's web site: Ruby helpers for processing # -# Copyright © 2018-2021 Nick Bowler +# Copyright © 2018-2022 Nick Bowler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,9 +16,11 @@ # along with this program. If not, see <https://www.gnu.org/licenses/>. require 'nokogiri' +require 'fastimage' -use_helper Nanoc::Helpers::Breadcrumbs use_helper Nanoc::Helpers::Blogging +use_helper Nanoc::Helpers::Breadcrumbs +use_helper Nanoc::Helpers::Rendering Xmlns = { 'xhtml' => 'http://www.w3.org/1999/xhtml' @@ -75,6 +77,95 @@ def counter(name = :default, item = @item) name.to_s.capitalize + " " + ($counters[item][name] += 1).to_s end +# Return a hash containing :src, :width and :height based on an image item rep. +def img_rep_attrs(item, rep) + rep = :large if item.reps[rep].raw_path.nil? + attrs = {} + + attrs[:src] ||= item_uri(item, rep: rep) + attrs[:width], attrs[:height] = FastImage.size(item.reps[rep].raw_path) + + return attrs +end + +def embed_img(item, rep: :large, caption: nil, block_attrs: {}, img_attrs: {}) + return "[image not found]" unless item + + img_attrs[:alt] ||= item[:title] + caption ||= img_attrs[:alt] + caption = caption.strip + caption.gsub!(/\s+/, " ") + + img_attrs = img_rep_attrs(item, rep).merge(img_attrs) + block_attrs[:href] = item_uri(item, rep: :info) + + b = Nokogiri::XML::Builder.new do |xml| + xml.a(block_attrs) { + xml.img(img_attrs) + unless caption.empty? + xml << " ⁠" + xml.small { xml << caption } + end + } + end + b.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::NO_DECLARATION) +end + +def gallery_img(item, rep: :medium, caption: nil, alt: nil) + attrs = { alt: alt, "generate-gallery" => "generate-gallery" } + embed_img(item, rep: rep, caption: caption, img_attrs: attrs) +end + +def floating_img(item, rep: :medium, caption: nil, alt: nil, left: nil) + battrs = { class: if left then "left" else "right" end } + attrs = { alt: alt } + + embed_img(item, rep: rep, caption: caption, + block_attrs: battrs, img_attrs: attrs) +end + +def expand_copyright(copyright) + result = { :years => {} } + + /^([-–[:digit:][:space:],]*)(.*)$/.match(copyright) do |m| + m[1].split(/\s*,\s*/).each do |range| + lo, hi = range.split(/[^[:digit:]]+/) + for y in (lo..hi||lo) + result[:years][y] = 1 + end + end + + result[:years] = result[:years].keys.sort + result[:name] = m[2] + return result + end + + return nil +end + +def path_to_rep(path) + @items.find_all(File::dirname(path) + "/*").each do |item| + item.reps.each do |rep| + return rep if rep.path == path + end + end + return nil +end + +def find_images(item = @item) + return [] if item.binary? + + result = {} + doc = Nokogiri::HTML(item.compiled_content(snapshot: :pre)) + doc.xpath("//img/@src").each do |imgsrc| + rep = path_to_rep(imgsrc.value) + if rep + result[rep.item.identifier] ||= rep.item + end + end + return result.values +end + def human_filesize(size) units = ["B", "KiB", "MiB", "GiB"] prec = 0 @@ -90,3 +181,7 @@ def human_filesize(size) sprintf("%.*f %s", prec, size + 0.05, unit) end + +def license_shortname(item) + item.fetch(:shortname, File::basename(item.identifier.without_ext).upcase) +end diff --git a/lib/imginfo.rb b/lib/imginfo.rb index 13d6b01..668cd5a 100644 --- a/lib/imginfo.rb +++ b/lib/imginfo.rb @@ -25,17 +25,18 @@ class ImgInfoFilter < Nanoc::Filter def do_variant(xml, name, item = @item, rep: :default) file = item.reps[rep].raw_path + unless file.nil? + w, h = FastImage.size(file) + sz = File.size(file) - w, h = FastImage.size(file) - sz = File.size(file) - - xml.variant { - xml.name(name) - xml.uri(item_uri(item, rep: rep)) - xml.width(w) - xml.height(h) - xml.filesize(human_filesize(sz)) - } + xml.variant { + xml.name(name) + xml.uri(item_uri(item, rep: rep)) + xml.width(w) + xml.height(h) + xml.filesize(human_filesize(sz)) + } + end end def run(filename, params = {}) @@ -44,6 +45,7 @@ class ImgInfoFilter < Nanoc::Filter b = Nokogiri::XML::Builder.new do |xml| xml.image { do_variant(xml, "Large", rep: :large) + do_variant(xml, "Medium", rep: :medium) do_variant(xml, "Original") diff --git a/lib/project-readme.rb b/lib/project-readme.rb index 3338e8a..079640e 100644 --- a/lib/project-readme.rb +++ b/lib/project-readme.rb @@ -1,6 +1,6 @@ # Nick's web site: Generate a project page from a submodule README.md # -# Copyright © 2021 Nick Bowler +# Copyright © 2021-2022 Nick Bowler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -82,21 +82,25 @@ def project_readme(item = @item) obtaining += line.lstrip end + gpg_keyid = "5B45D3D185B8E1F6" obtaining += "\n\n" + <<~EOF [gpg]: https://gnupg.org/ + [keyring]: /pubring/#{gpg_keyid}.asc Use the signature file to verify that the corresponding source bundle is intact. After downloading both files, if [GnuPG][gpg] is installed, the signature can be verified with a command like: - <kbd>gpg --verify #{targz}.sig</kbd> + <kbd>gpg --verify #{targz}.sig #{targz}</kbd> If the verification fails because you don't have the required public key, that key can be imported with a command such as: - <kbd>gpg --keyserver keys.gnupg.net --recv-keys 5B45D3D185B8E1F6</kbd> + <kbd>gpg --keyserver keys.draconx.ca --recv-keys #{gpg_keyid}</kbd> - Then run the verify command again. + Then run the verify command again. Alternatively, you can + [download the public keyring][keyring] manually and import it + using `gpg --import`. EOF end diff --git a/lib/scss-var.rb b/lib/scss-var.rb index c6cf654..b15680f 100644 --- a/lib/scss-var.rb +++ b/lib/scss-var.rb @@ -1,6 +1,6 @@ # Nick's web site: Helper to retrieve global style variables in ruby. # -# Copyright © 2020 Nick Bowler +# Copyright © 2020, 2022 Nick Bowler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -22,11 +22,9 @@ class GetSCSSGlobals < Sass::Tree::Visitors::Perform x = new(nil) x.send(:visit, root) result = x.instance_variable_get(:@globals) - if name.nil? - return result.freeze - else - return result[name] - end + return result.freeze if name.nil? + + x.send(:rubify_result, result[name]) end protected @@ -40,15 +38,35 @@ class GetSCSSGlobals < Sass::Tree::Visitors::Perform def visit_variable(node) super - + x = @environment.global_env.var(node.name) - if !x.nil? - @globals[node.name] = x + @globals[node.name] = x unless x.nil? + end + + # Convert SASS maps and lists to ruby equivalents that are actually usable. + def rubify_result(val) + case val + when Sass::Script::Value::Map + val.to_h.each_with_object({}) do |(k, v), h| + h[k.to_s.to_sym] = rubify_result(v) + end + when Sass::Script::Value::List + val.to_a.map { |v| rubify_result(v) } + else + val end end end def scss_get_var(variable, item = @items["/style.scss"]) - engine = Sass::Engine.for_file(item.raw_filename, { :syntax => :scss }) + engine = Sass::Engine.for_file(item.raw_filename, { + :syntax => :scss, + :load_paths => ["."], + }) return GetSCSSGlobals.visit(engine.to_tree, variable) end + +def scss_get_colour(colour, index = 0, item = @items["/style.scss"]) + cmap = scss_get_var(:colourmap, item); + [cmap[colour]].flatten[index] +end diff --git a/tools/weblog-update.rb b/tools/weblog-update.rb index f955f24..677f367 100755 --- a/tools/weblog-update.rb +++ b/tools/weblog-update.rb @@ -29,7 +29,7 @@ if content =~ /\A---(--)?\s*$/ end if metadata - meta = YAML.load(metadata) + meta = YAML.load(metadata, permitted_classes: [Time]) timefmt = "%FT%T%z" updatestr = updatetime.round.strftime(timefmt) autoset = nil @@ -49,7 +49,7 @@ if metadata if autoset # Revalidate YAML - meta = YAML.load(metadata) + meta = YAML.load(metadata, permitted_classes: [Time]) unless meta[autoset] == updatetime.round raise "failed to auto-insert " + autoset end