Release slotifier-1.
authorNick Bowler <nbowler@draconx.ca>
Sun, 14 Feb 2021 19:26:35 +0000 (14:26 -0500)
committerNick Bowler <nbowler@draconx.ca>
Sun, 14 Feb 2021 20:54:52 +0000 (15:54 -0500)
Mostly a trial to see if we can get all the infrastructure in place
to release tarballs tarballs on the website.  Newly introduced is
an "archive" directory, which provides for browseable file listings,
as well as the ability to link to the most recent tar file in the
generated project descriptions.

13 files changed:
Rules
content/archive/slotifier/slotifier-1.tar.gz [new symlink]
content/archive/slotifier/slotifier-1.tar.gz.sig [new symlink]
content/images/folder.svg [new file with mode: 0644]
content/images/return.svg [new file with mode: 0644]
content/projects/slotifier.md
content/style.scss
gitmodules/slotifier
layouts/default.xml
layouts/default.xsl
layouts/listing.xhtml [new file with mode: 0644]
lib/helpers.rb
lib/project-readme.rb

diff --git a/Rules b/Rules
index d48f28743b7dc089988e1ddc5f77faa3605003b0..2460c14ba315339e7e4ca55479480101b97a6de1 100644 (file)
--- a/Rules
+++ b/Rules
@@ -49,6 +49,25 @@ preprocess do
         item[:updated_at] ||=
             item[:updated] || File.stat(item.raw_filename).mtime
     end
+
+    archivedirs = {}
+    @items.find_all('/archive/**/*').each do |item|
+        dir = File.dirname(item.identifier)
+        while dir != "/"
+            archivedirs[dir] = true
+            dir = File.dirname(dir)
+        end
+    end
+
+    archivedirs.keys.sort_by{ |s| -s.length }.each do |dir|
+        attrs = {
+            pattern: "#{dir}/*{,/index.lst}",
+            title: "Index of #{dir}",
+            gitrev: commit,
+        }
+
+        @items.create("", attrs, "#{dir}/index.lst")
+    end
 end
 
 postprocess do
@@ -72,6 +91,8 @@ postprocess do
         Open3.popen2("git", "-c", "core.bare=false", "annex", "registerurl") do
         |stdin, stdout, result|
             @items.each do |item|
+                next if item.raw_filename.nil?
+
                 l = File.readlink(item.raw_filename)
                 next unless l =~ %r{/annex/objects/}
 
@@ -107,6 +128,17 @@ postprocess do
     end
 end
 
+compile '/**/index.lst' do
+    layout '/listing.xhtml'
+    filter :erb
+    layout '/default.xml'
+    layout '/default.xsl'
+    filter :relativize_paths, type: :xml
+    filter :xhtml_compat
+    filter :remove_wj
+    write item.identifier.without_ext + ".xhtml"
+end
+
 compile '/license/gpl*.md' do
     filter :kramdown, auto_ids: false, header_offset: -1
     layout '/default.xml'
diff --git a/content/archive/slotifier/slotifier-1.tar.gz b/content/archive/slotifier/slotifier-1.tar.gz
new file mode 120000 (symlink)
index 0000000..b0fdf2a
--- /dev/null
@@ -0,0 +1 @@
+../../../.git/annex/objects/M6/75/SHA512-s650123--072fbd99ff994c48b835032105f93010f5860246c8e1576929ff9fa904319dbb627e4d09224dd91924c83b71d2ce75fcf1206f84d73d352fa4b7376238a867c6/SHA512-s650123--072fbd99ff994c48b835032105f93010f5860246c8e1576929ff9fa904319dbb627e4d09224dd91924c83b71d2ce75fcf1206f84d73d352fa4b7376238a867c6
\ No newline at end of file
diff --git a/content/archive/slotifier/slotifier-1.tar.gz.sig b/content/archive/slotifier/slotifier-1.tar.gz.sig
new file mode 120000 (symlink)
index 0000000..2a96fa5
--- /dev/null
@@ -0,0 +1 @@
+../../../.git/annex/objects/5q/G1/SHA512-s310--910f2cb0a1e665756be0e19cac03288ef2c0bf53c8b3b4e78c76bbf5a8e1a240b0f90d5e397dc1335623b4782beb56a5ab2fb7cbc86aca639e65a81ea1a0a91e/SHA512-s310--910f2cb0a1e665756be0e19cac03288ef2c0bf53c8b3b4e78c76bbf5a8e1a240b0f90d5e397dc1335623b4782beb56a5ab2fb7cbc86aca639e65a81ea1a0a91e
\ No newline at end of file
diff --git a/content/images/folder.svg b/content/images/folder.svg
new file mode 100644 (file)
index 0000000..79b25c3
--- /dev/null
@@ -0,0 +1,424 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48.000000px"
+   height="48.000000px"
+   id="svg97"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/places"
+   sodipodi:docname="folder.svg"
+   inkscape:export-filename="/home/jimmac/Desktop/horlander-style3.png"
+   inkscape:export-xdpi="90.000000"
+   inkscape:export-ydpi="90.000000"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs3">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective68" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient6719"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5060">
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0"
+         id="stop5062" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5064" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient6717"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       id="linearGradient5048">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop5050" />
+      <stop
+         id="stop5056"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5052" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5048"
+       id="linearGradient6715"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       x1="302.85715"
+       y1="366.64789"
+       x2="302.85715"
+       y2="609.50507" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient9806">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop9808" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop9810" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9766">
+      <stop
+         style="stop-color:#6194cb;stop-opacity:1;"
+         offset="0"
+         id="stop9768" />
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1;"
+         offset="1"
+         id="stop9770" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3096">
+      <stop
+         id="stop3098"
+         offset="0"
+         style="stop-color:#424242;stop-opacity:1;" />
+      <stop
+         id="stop3100"
+         offset="1.0000000"
+         style="stop-color:#777777;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient319"
+       inkscape:collect="always">
+      <stop
+         id="stop320"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop321"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient1789">
+      <stop
+         style="stop-color:#202020;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop1790" />
+      <stop
+         style="stop-color:#b9b9b9;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop1791" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1789"
+       id="radialGradient238"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.055022,-2.734504e-2,0.177703,1.190929,-3.572177,-7.125301)"
+       cx="20.706017"
+       cy="37.517986"
+       fx="20.706017"
+       fy="37.517986"
+       r="30.905205" />
+    <linearGradient
+       id="linearGradient3983">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.87628865;"
+         offset="0.0000000"
+         id="stop3984" />
+      <stop
+         style="stop-color:#fffffe;stop-opacity:0.0000000;"
+         offset="1.0000000"
+         id="stop3985" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3983"
+       id="linearGradient491"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.516844,0.000000,0.000000,0.708978,-0.879573,-1.318166)"
+       x1="6.2297964"
+       y1="13.773066"
+       x2="9.8980894"
+       y2="66.834053" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="46.689312"
+       x2="12.853771"
+       y1="32.567184"
+       x1="13.035696"
+       gradientTransform="matrix(1.317489,0.000000,0.000000,0.816256,-0.879573,-1.318166)"
+       id="linearGradient322"
+       xlink:href="#linearGradient319"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="6.1802502"
+       x2="15.514889"
+       y1="31.367750"
+       x1="18.112709"
+       id="linearGradient3104"
+       xlink:href="#linearGradient3096"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient9766"
+       id="linearGradient9772"
+       x1="22.175976"
+       y1="36.987999"
+       x2="22.065331"
+       y2="32.050499"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient9806"
+       id="radialGradient9812"
+       cx="24.35099"
+       cy="41.591846"
+       fx="24.35099"
+       fy="41.591846"
+       r="19.136078"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.242494,1.565588e-16,31.50606)"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     fill="#729fcf"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.10196078"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="4"
+     inkscape:cx="54.359127"
+     inkscape:cy="-13.803699"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1026"
+     inkscape:window-height="818"
+     inkscape:window-x="169"
+     inkscape:window-y="30"
+     inkscape:showpageshadow="false"
+     stroke="#3465a4" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Folder Icon</dc:title>
+        <dc:date />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>folder</rdf:li>
+            <rdf:li>directory</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Folder"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       transform="matrix(2.262383e-2,0,0,2.086758e-2,43.38343,36.36962)"
+       id="g6707">
+      <rect
+         style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         id="rect6709"
+         width="1339.6335"
+         height="478.35718"
+         x="-1559.2523"
+         y="-150.69685" />
+      <path
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+         id="path6711"
+         sodipodi:nodetypes="cccc" />
+      <path
+         sodipodi:nodetypes="cccc"
+         id="path6713"
+         d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    </g>
+    <path
+       d="M 4.5217805,38.687417 C 4.5435766,39.103721 4.9816854,39.520026 5.3979900,39.520026 L 36.725011,39.520026 C 37.141313,39.520026 37.535823,39.103721 37.514027,38.687417 L 36.577584,11.460682 C 36.555788,11.044379 36.117687,10.628066 35.701383,10.628066 L 22.430510,10.628066 C 21.945453,10.628066 21.196037,10.312477 21.028866,9.5214338 L 20.417475,6.6283628 C 20.262006,5.8926895 19.535261,5.5904766 19.118957,5.5904766 L 4.3400975,5.5904766 C 3.9237847,5.5904766 3.5292767,6.0067807 3.5510726,6.4230849 L 4.5217805,38.687417 z "
+       id="path216"
+       style="fill:url(#radialGradient238);fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#linearGradient3104);stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+       sodipodi:nodetypes="ccccccssssccc" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path9788"
+       d="M 5.2265927,22.5625 L 35.492173,22.5625"
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path9784"
+       d="M 5.0421736,18.5625 L 35.489104,18.5625"
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 4.9806965,12.5625 L 35.488057,12.5625"
+       id="path9778"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 5.3861577,32.5625 L 35.494881,32.5625"
+       id="path9798"
+       sodipodi:nodetypes="cc" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path9800"
+       d="M 5.5091398,34.5625 L 35.496893,34.5625"
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 5.0421736,16.5625 L 35.489104,16.5625"
+       id="path9782"
+       sodipodi:nodetypes="cc" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path9780"
+       d="M 5.0114345,14.5625 L 35.48858,14.5625"
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path9776"
+       d="M 4.9220969,10.5625 L 20.202912,10.5625"
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.99999982;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 4.8737534,8.5624999 L 19.657487,8.5624999"
+       id="path9774"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 5.3246666,28.5625 L 35.493876,28.5625"
+       id="path9794"
+       sodipodi:nodetypes="cc" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path9792"
+       d="M 5.2880638,26.5625 L 35.493184,26.5625"
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 5.2265927,24.5625 L 35.492173,24.5625"
+       id="path9790"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 5.1958537,20.5625 L 35.491649,20.5625"
+       id="path9786"
+       sodipodi:nodetypes="cc" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path9796"
+       d="M 5.3246666,30.5625 L 35.493876,30.5625"
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    <path
+       style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 5.5091398,36.5625 L 35.496893,36.5625"
+       id="path9802"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="color:#000000;fill:url(#linearGradient491);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.2138050;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:block;overflow:visible;opacity:0.45142857"
+       d="M 6.0683430,38.864023 C 6.0846856,39.176251 5.8874317,39.384402 5.5697582,39.280326 L 5.5697582,39.280326 C 5.2520766,39.176251 5.0330270,38.968099 5.0166756,38.655870 L 4.0689560,6.5913839 C 4.0526131,6.2791558 4.2341418,6.0906134 4.5463699,6.0906134 L 18.968420,6.0429196 C 19.280648,6.0429196 19.900363,6.3433923 20.101356,7.3651014 L 20.674845,10.180636 C 20.247791,9.7153790 20.255652,9.7010175 20.037287,9.0239299 L 19.631192,7.7647478 C 19.412142,7.0371009 18.932991,6.9328477 18.620763,6.9328477 L 5.7329889,6.9328477 C 5.4207613,6.9328477 5.2235075,7.1409999 5.2398583,7.4532364 L 6.1778636,38.968099 L 6.0683430,38.864023 z "
+       id="path219"
+       sodipodi:nodetypes="cccccccccscccccc" />
+    <g
+       style="stroke-miterlimit:4.0000000;stroke-width:0.99946535;stroke:none;fill-rule:nonzero;fill-opacity:0.75706214;fill:#ffffff"
+       id="g220"
+       transform="matrix(1.040764,0.000000,5.449252e-2,1.040764,-8.670199,2.670594)"
+       inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+       inkscape:export-xdpi="74.800003"
+       inkscape:export-ydpi="74.800003">
+      <path
+         style="fill-opacity:0.50847459;fill:#ffffff"
+         d="M 42.417183,8.5151772 C 42.422267,8.4180642 42.289022,8.2681890 42.182066,8.2681716 L 29.150665,8.2660527 C 29.150665,8.2660527 30.062379,8.8540072 31.352477,8.8622963 L 42.405974,8.9333167 C 42.417060,8.7215889 42.408695,8.6772845 42.417183,8.5151772 z "
+         id="path221"
+         sodipodi:nodetypes="cscscs" />
+    </g>
+    <path
+       style="color:#000000;fill:url(#linearGradient9772);fill-opacity:1.0;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1;visibility:visible;display:block"
+       d="M 39.783532,39.510620 C 40.927426,39.466556 41.746608,38.414321 41.830567,37.189615 C 42.622354,25.640928 43.489927,15.957666 43.489927,15.957666 C 43.562082,15.710182 43.322016,15.462699 43.009787,15.462699 L 8.6386304,15.462699 C 8.6386304,15.462699 6.7883113,37.329591 6.7883113,37.329591 C 6.6737562,38.311657 6.3223038,39.134309 5.2384755,39.513304 L 39.783532,39.510620 z "
+       id="path233"
+       sodipodi:nodetypes="cscccscc"
+       inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+       inkscape:export-xdpi="74.800003"
+       inkscape:export-ydpi="74.800003" />
+    <path
+       sodipodi:nodetypes="ccsscsc"
+       id="path304"
+       d="M 9.6202444,16.463921 L 42.411343,16.528735 L 40.837297,36.530714 C 40.752975,37.602225 40.386619,37.958929 38.964641,37.958929 C 37.093139,37.958929 10.286673,37.926522 7.569899,37.926522 C 7.8034973,37.605711 7.9036547,36.937899 7.9049953,36.92191 L 9.6202444,16.463921 z "
+       style="opacity:0.46590909;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient322);stroke-width:0.99999970px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+    <path
+       sodipodi:nodetypes="ccccc"
+       id="path323"
+       d="M 9.6202481,16.223182 L 8.4536014,31.866453 C 8.4536014,31.866453 16.749756,27.718375 27.119949,27.718375 C 37.490142,27.718375 42.675239,16.223182 42.675239,16.223182 L 9.6202481,16.223182 z "
+       style="fill:#ffffff;fill-opacity:0.089285679;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="pattern" />
+</svg>
diff --git a/content/images/return.svg b/content/images/return.svg
new file mode 100644 (file)
index 0000000..d3cce96
--- /dev/null
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="90.000000"
+   inkscape:export-xdpi="90.000000"
+   inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+   width="48px"
+   height="48px"
+   id="svg11300"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions"
+   sodipodi:docname="edit-undo.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs3">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective31" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2326">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2328" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2330" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2316">
+      <stop
+         style="stop-color:#c4a000;stop-opacity:1;"
+         offset="0"
+         id="stop2318" />
+      <stop
+         style="stop-color:#c4a000;stop-opacity:0;"
+         offset="1"
+         id="stop2320" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2308">
+      <stop
+         style="stop-color:#edd400;stop-opacity:1;"
+         offset="0"
+         id="stop2310" />
+      <stop
+         style="stop-color:#edd400;stop-opacity:0;"
+         offset="1"
+         id="stop2312" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8662">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop8664" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop8666" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8662"
+       id="radialGradient8668"
+       cx="24.837126"
+       cy="36.421127"
+       fx="24.837126"
+       fy="36.421127"
+       r="15.644737"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-6.227265e-14,16.87306)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient2187"
+       inkscape:collect="always">
+      <stop
+         id="stop2189"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2191"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2187"
+       id="linearGradient1764"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1.813471e-16,-1.171926,-1.171926,1.813471e-16,46.17440,54.10111)"
+       x1="17.060806"
+       y1="11.39502"
+       x2="12.624337"
+       y2="12.583769" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2308"
+       id="linearGradient2314"
+       x1="26.5"
+       y1="34.25"
+       x2="26.25"
+       y2="43.571831"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2316"
+       id="linearGradient2322"
+       x1="26.5"
+       y1="34.25"
+       x2="26.25"
+       y2="43.571831"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2326"
+       id="radialGradient2332"
+       cx="15.09403"
+       cy="13.282721"
+       fx="15.09403"
+       fy="13.282721"
+       r="10.16466"
+       gradientTransform="matrix(2.496031,-1.151905e-16,1.061756e-16,2.300689,-25.12402,-17.82636)"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#c4a000"
+     fill="#edd400"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.25490196"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.8284271"
+     inkscape:cx="-19.855325"
+     inkscape:cy="-15.183692"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="891"
+     inkscape:window-height="818"
+     inkscape:window-x="0"
+     inkscape:window-y="30" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:title>Edit Undo</dc:title>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>edit</rdf:li>
+            <rdf:li>undo</rdf:li>
+            <rdf:li>revert</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <path
+       transform="matrix(-1.489736,0.000000,0.000000,-1.001252,60.60436,75.31260)"
+       d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1  9.1923885,36.421127 A 15.644737 8.3968935 0 1 1  40.481863 36.421127 z"
+       sodipodi:ry="8.3968935"
+       sodipodi:rx="15.644737"
+       sodipodi:cy="36.421127"
+       sodipodi:cx="24.837126"
+       id="path8660"
+       style="opacity:0.14117647;color:#000000;fill:url(#radialGradient8668);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       sodipodi:type="arc" />
+    <path
+       style="opacity:1;color:#000000;fill:url(#linearGradient2314);fill-opacity:1.0;fill-rule:nonzero;stroke:url(#linearGradient2322);stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+       d="M 9.582441,45.034369 C 49.608249,46.355509 43.282405,12.29355 22.462411,12.49765 L 22.462411,3.1222396 L 5.8139298,17.708819 L 22.462411,33.006349 C 22.462411,33.006349 22.462411,23.337969 22.462411,23.337969 C 36.525521,22.751999 40.639939,44.770549 9.582441,45.034369 z "
+       id="path1432"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       sodipodi:nodetypes="ccccccc"
+       id="path2177"
+       d="M 31.032281,39.315519 C 42.75538,33.235892 39.220073,13.087489 21.448701,13.549959 L 21.448701,5.4508678 C 21.448701,5.4508678 7.4009628,17.714589 7.4009628,17.714589 L 21.448701,30.658617 C 21.448701,30.658617 21.448701,22.380979 21.448701,22.380979 C 36.288551,22.032709 35.608611,35.138579 31.032281,39.315519 z "
+       style="opacity:0.69886361;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1764);stroke-width:0.9999997;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+    <path
+       style="opacity:0.51136364;color:#000000;fill:url(#radialGradient2332);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 6.6291261,17.682797 L 12.28598,23.074486 C 18.561553,22.897709 15.733126,16.710525 26.958446,13.616933 L 22.008699,12.998214 L 21.92031,4.3361562 L 6.6291261,17.682797 z "
+       id="path2324"
+       sodipodi:nodetypes="cccccc" />
+  </g>
+</svg>
index 9e846b42630127a94cfdb4042a2ab8296a5e2f15..2a00479d13a4af1b9f188b760c0c9361fc99a010 100644 (file)
@@ -3,6 +3,7 @@ title: Slotifier
 copyright: 2021 Nick Bowler
 license: gpl-3 or (at your option) any later version
 module: slotifier
+release: v1
 ---
 
 <%= project_readme %>
index 82b872028fc1db23c80e229cbcc3a0b33f59196f..0c56cc4bb4d8f31ac75650c5c1013d7550098a02 100644 (file)
@@ -137,6 +137,19 @@ table.cc {
     }
 }
 
+table.filelist {
+    &>tr>*:first-child, &>*>tr>*:first-child {
+        &+td { min-width: 50%; }
+        width: 0;
+    }
+
+    img {
+        display: block;
+        height: 1.5em;
+        width: auto;
+    }
+}
+
 // Site header rules
 #breadcrumbs>*, #sitetitle>* { font-size: 0.8em; }
 #breadcrumbs {
index dd3142f8ab42703ccb91cd9a3e21ded0801bd228..d30a4f5730dc9358523db5129a85b1f62c82981a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit dd3142f8ab42703ccb91cd9a3e21ded0801bd228
+Subproject commit d30a4f5730dc9358523db5129a85b1f62c82981a
index 6ae8b307a20599f98db9b3b2491c345d7cc17f36..949290a5af4d29559336c5eccb0cabc282f1a06d 100644 (file)
   </license>
 <% end
 %>  <source>
+<% if @item.raw_filename %>
     <file><%= item_source(@item) %></file>
-    <revision><%= item.fetch(:gitrev) %></revision>
+<% elsif File.basename(@item.identifier) == "index.lst" %>
+    <dir><%= "content" + File.dirname(@item.identifier) %></dir>
+<% end %>
+    <revision><%= @item.fetch(:gitrev) %></revision>
     <compiletime><%=
       Time.now.gmtime.strftime "%Y-%m-%d %H:%M UTC"
     %></compiletime>
index f41467bd87e01d6de9a7aa0d594ab074f16ac494..075ad184a71b4dfe53a5f9b8d29f29b95b5c78b0 100644 (file)
@@ -34,7 +34,7 @@
   cdata-section-elements='style' />
 
 <xsl:param name='source-uri'
-  select='"//git.draconx.ca/gitweb/homepage.git/blob/"' />
+  select='"//git.draconx.ca/gitweb/homepage.git/"' />
 <xsl:param name='site-title' select='"The Citrine Citadel"' />
 <xsl:param name='section-links' select='//document/section-links' />
 
   </p>
 </xsl:template>
 
+<func:function name='f:matching-child'>
+  <xsl:param name='child' select='./copyright-holder' />
+  <xsl:param name='node' select='.' />
+  <xsl:param name='nodeset' select='$node/../*[name()=name($node)]' />
+
+  <func:result select='$nodeset[*[name()=name($child)]=$child]' />
+</func:function>
+
+<func:function name='f:attribution-order'>
+  <xsl:param name='a' />
+  <xsl:param name='b' />
+
+  <xsl:variable name='docmatch'
+    select='number($a/copyright-holder = /document/copyright-holder)
+            - number($b/copyright-holder = /document/copyright-holder)' />
+
+  <xsl:variable name='authmatch'
+    select='count(f:matching-child($a/copyright-holder, $a))
+            - count(f:matching-child($b/copyright-holder, $b))' />
+
+  <xsl:variable name='licmatch'
+    select='count(f:matching-child($a/license, $a))
+            - count(f:matching-child($b/license, $b))' />
+
+  <xsl:choose>
+    <xsl:when test='$docmatch'><func:result select='$docmatch' /></xsl:when>
+    <xsl:when test='$authmatch'><func:result select='$authmatch' /></xsl:when>
+    <xsl:when test='$licmatch'><func:result select='$licmatch' /></xsl:when>
+    <xsl:otherwise><func:result select='"nope"' /></xsl:otherwise>
+  </xsl:choose>
+</func:function>
+
+<xsl:template match='image/license'>
+  <xsl:text>, </xsl:text>
+  <a href='{uri}' rel='license'><xsl:value-of select='shortname' /></a>
+</xsl:template>
+
+<xsl:template match='image'>
+  <xsl:choose>
+    <xsl:when test='position() = 1'>, except </xsl:when>
+    <xsl:when test='position() = last()'> and </xsl:when>
+    <xsl:otherwise>, </xsl:otherwise>
+  </xsl:choose>
+  <a href='{uri}'><xsl:value-of select='title' /></a>
+  <xsl:text> © </xsl:text>
+  <xsl:value-of select='copyright' />
+  <xsl:apply-templates select='license' />
+</xsl:template>
+
+<xsl:template name='image-attribution'>
+<!--
+  <xsl:variable name='x' select='/document/image[copyright-holder="Nick Bowler"][1]' />
+  <xsl:variable name='y' select='/document/image[copyright-holder="Nick Bowler"][4]' />
+-->
+  <xsl:variable name='images-fragment'>
+    <xsl:for-each select='/document/image'>
+      <xsl:sort select='number(copyright-holder = /document/copyright-holder)'
+                data-type='number' order='descending' />
+      <xsl:sort select='count(f:matching-child(copyright-holder))'
+                data-type='number' order='descending' />
+      <xsl:sort select='copyright-holder' order='descending' />
+      <xsl:sort select='count(f:matching-child(license))'
+                data-type='number' order='descending' />
+      <xsl:sort select='license/identifier' order='descending' />
+
+      <xsl:call-template name='notransform' />
+    </xsl:for-each>
+  </xsl:variable>
+  <xsl:variable name='images' select='exslt:node-set($images-fragment)/*' />
+
+  <xsl:variable name='abbrev-split'
+      select='count($images[copyright-holder = $images[1]/copyright-holder
+                 and license/identifier = $images[1]/license/identifier])' />
+
+  <xsl:variable name='abbrev-years-fragment'>
+    <xsl:for-each select='$images[$abbrev-split >= position()]/copyright-year'>
+      <xsl:sort data-type='number' />
+      <copyright-year><xsl:value-of select='.' /></copyright-year>
+    </xsl:for-each>
+  </xsl:variable>
+  <xsl:variable name='abbrev-years'
+    select='exslt:node-set($abbrev-years-fragment)/*' />
+
+  <p>
+    <xsl:text>Images © </xsl:text>
+    <xsl:value-of select='$abbrev-years[1]' />
+    <xsl:if test='$abbrev-years[last()] != $abbrev-years[1]'>
+      <xsl:value-of select='concat("–", $abbrev-years[last()])' />
+    </xsl:if>
+    <xsl:value-of select='concat(" ", $images[1]/copyright-holder)' />
+    <xsl:apply-templates select='$images[1]/license' />
+    <xsl:apply-templates select='$images[position() > $abbrev-split]' />
+    <xsl:text>.</xsl:text>
+  </p>
+</xsl:template>
+
 <xsl:template match='source'>
   <p>
-    <xsl:text>This document was compiled from </xsl:text>
-    <a href='{concat($source-uri, revision, ":", file)}'>
-      <xsl:value-of select='file' />
-    </a>
+    <xsl:text>This document was compiled</xsl:text>
+    <xsl:choose>
+      <xsl:when test='file'>
+        <xsl:text> from </xsl:text>
+        <a href='{concat($source-uri, "blob/", revision, ":", file)}'>
+          <xsl:value-of select='file' />
+        </a>
+      </xsl:when>
+      <xsl:when test='dir'>
+        <xsl:text> from </xsl:text>
+        <a href='{concat($source-uri, "tree/", revision, ":", dir)}'>
+          <xsl:value-of select='dir' />
+        </a>
+      </xsl:when>
+    </xsl:choose>
     <xsl:text> on </xsl:text>
     <xsl:value-of select='compiletime' />
     <xsl:text>.</xsl:text>
diff --git a/layouts/listing.xhtml b/layouts/listing.xhtml
new file mode 100644 (file)
index 0000000..2e053d5
--- /dev/null
@@ -0,0 +1,79 @@
+<%
+# Nick's web site: Generate directory listing.
+#
+# Copyright © 2021 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/>
+
+mydir = rep_uri
+
+files = {}
+@items.find_all(@item[:pattern]).each do |item|
+  t = item[:updated_at]
+
+  item.reps.each do |rep|
+    next if rep == @rep
+
+    p = rep_uri(rep)
+    d, f = File.split(p)
+    next unless "#{d}/" == mydir
+
+    if p =~ %r{/$}
+      sz = Dir.children(File.dirname(rep.raw_path)).length - 1
+      type = "DIR"
+    else
+      sz = human_filesize(File.size(rep.raw_path))
+      type = nil
+    end
+
+    files[f] = {
+      mtime: if t then t.getutc.strftime "%Y-%m-%d %H:%M UTC" end,
+      size: sz,
+      type: type,
+    }
+  end
+end
+
+if @items["#{File.dirname(mydir)}/index.lst"]
+  files[".."] = { type: "UP" }
+end
+%>
+<table class='filelist'>
+  <thead>
+    <tr><th /><th>Name</th><th>Last Modified</th><th>Size</th></tr>
+  </thead>
+  <tbody>
+<% files.keys.sort.each do |key| %>
+    <tr>
+      <td>
+<% if files[key][:type] %>
+        <div>
+          <img src='<%=
+            case files[key][:type]
+            when "DIR"; "/images/folder.svg"
+            when "UP";  "/images/return.svg"
+            else raise "no icon for filetype #{files[key][:type]}"
+            end %>' alt='<%= files[key][:type] %>' width='16' height='16' />
+        </div>
+<% end %>
+      </td>
+      <td><a href='<%= key %>'><%=
+        if key == ".." then "[Parent Directory]" else key end
+      %></a></td>
+      <td><%= files[key][:mtime] %></td>
+      <td><%= files[key][:size] %></td>
+    </tr>
+<% end %>
+  </tbody>
+</table>
index df48f4c745d72de52464aea6da333e61e97e6df4..c9a1cc3d503f343e63175bce9695c39d3e11b989 100644 (file)
@@ -1,6 +1,6 @@
 # Nick's web site: Ruby helpers for processing
 #
-# Copyright © 2018-2019 Nick Bowler
+# Copyright © 2018-2021 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
@@ -44,7 +44,11 @@ def item_source(item = @item)
 end
 
 def item_uri(item = @item, rep: :default)
-    return item.path(rep: rep).gsub(/\/index.[^.]*$/, "/")
+    return item.path(rep: rep).sub(%r{/index[.][^.]*$}, "/")
+end
+
+def rep_uri(rep = @rep)
+    return rep.path.sub(%r{/index[.][^.]*$}, "/")
 end
 
 def find_license(license)
@@ -73,6 +77,7 @@ end
 
 def human_filesize(size)
     units = ["B", "KiB", "MiB", "GiB"]
+    prec = 0
 
     for unit in units
         if (size < 1024)
@@ -80,7 +85,8 @@ def human_filesize(size)
         end
 
         size /= 1024.0
+        prec = 1
     end
 
-    sprintf("%.1f %s", size + 0.05, unit)
+    sprintf("%.*f %s", prec, size + 0.05, unit)
 end
index 1e1fa874631a1cef261ff0eaa8d8dcb1e2fa7232..74691716065c476adc841d665c341d4b5f3a9270 100644 (file)
 
 def project_readme(item = @item)
     tag = item.fetch(:release, "HEAD")
-    shortname = item.fetch(:shortname, item[:title].downcase)
+    shortname = item.fetch(:shortname, item[:module])
 
     data, status = Open3.capture2("git", "submodule", "foreach", "--quiet",
       "case $sm_path in */" + item[:module] + ")" +
-      "git remote get-url origin || echo;" +
-      "git show " + tag + ":README.md ;;" +
+      "git fetch --quiet --tags;" +
+      "git log --max-count=1 --format=%cI #{tag}; printf '\\35';" +
+      "git show #{tag}:NEWS 2>/dev/null; printf '\\35';" +
+      "git remote get-url origin; printf '\\35';" +
+      "git show #{tag}:README.md ;;" +
       "esac")
     raise "git submodule foreach failed" if status != 0
 
-    gituri, contents = data.split("\n", 2)
+    date, news, gituri, contents = data.split("\35", 4)
     intro, contents = contents.split("#", 2)
     contents = if contents.nil? then "" else "\n#" + contents end
 
+    gituri.strip!
     gitweb = gituri.sub(%r{^[^/]*(.*)(/.*)}, '\1/gitweb\2')
+    date = Date.iso8601(date).to_time
 
     obtaining = <<~EOF
         # Obtaining #{item[:title]}
     EOF
 
     if item[:release].nil?
-        obtaining += <<~EOF
+        obtaining += "\n" + <<~EOF
             There are presently no released versions of #{shortname}.
         EOF
     else
-        # TODO
+        newsver, news = news.split("\n", 2)
+        newsver.sub!(/^.*([[:digit:]][^:]*).*$/, '\1')
+
+        targz = "#{shortname}-#{newsver}.tar.gz"
+        distbase = "/archive/#{shortname}"
+        obtaining += <<~EOF
+            [archive]: #{distbase}
+
+            All released files are available from the [#{shortname} archive
+            directory][archive].
+        EOF
     end
 
     obtaining += <<~EOF
@@ -51,5 +66,39 @@ def project_readme(item = @item)
         <kbd>git clone #{gituri}</kbd>
     EOF
 
-    return intro + obtaining + contents
+    unless item[:release].nil?
+        obtaining += "\n" + <<~EOF
+            [targz]: #{distbase}/#{targz}
+            [targzsig]: #{distbase}/#{targz}.sig
+
+            The most recent release is version #{newsver}, released on
+            #{date.getutc.strftime("%Y-%m-%d")}.  Source code for this version
+            is available in [#{targz}][targz] ([signature][targzsig]).
+            Noteworthy changes in this release:
+        EOF
+        obtaining += "\n"
+        news.each_line do |line|
+            break if line =~ /^[^[:space:]]/
+            obtaining += line.lstrip
+        end
+
+        obtaining += "\n\n" + <<~EOF
+            [gpg]: https://gnupg.org/
+
+            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>
+
+            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>
+
+            Then run the verify command again.
+        EOF
+    end
+
+    return "#{intro}\n\n#{obtaining}\n\n#{contents}"
 end