+++ /dev/null
-<%
-# 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{/$}
- displaysize = Dir.children(File.dirname(rep.raw_path)).length - 1
- size = displaysize - 1000000
- type = :DIR
- else
- size = File.size(rep.raw_path)
- displaysize = human_filesize(size)
- type = nil
- end
-
- files[f] = {
- sorttime: if t then t.to_f else 0.0 end,
- displaytime: if t then t.getutc.strftime "%Y-%m-%d %H:%M UTC" end,
- displaysize: displaysize,
- size: size,
- type: type,
- }
- end
-end
-
-if @items["#{File.dirname(mydir)}/index.lst"]
- files[".."] = { type: :UP }
-end
-
-def render_entry(files, key)
- f = files[key]
- return <<~EOF
- <td>#{if f[:type]
- "<img alt='#{f[:type]}' width='16' height='16' src='#{case f[:type]
- when :DIR; "/images/folder.svg"
- when :UP; "/images/return.svg"
- else raise "no icon for filetype #{f[:type]}"
- end}' />"
- end}</td>
- <td><a href='#{key}'>#{
- if key == ".." then "[Parent Directory]" else key end
- }</a></td>
- <td>#{f[:displaytime]}</td>
- <td>#{f[:displaysize]}</td>
- EOF
-end
-%>
-<div>
-<script type='x'><![CDATA[]]x><!--]]></script>
-<input style='display: none' type='radio' name='filelist-sort' id='filelist-name-sort' checked='checked' />
-<input style='display: none' type='radio' name='filelist-sort' id='filelist-date-sort' />
-<input style='display: none' type='radio' name='filelist-sort' id='filelist-size-sort' />
-<input style='display: none' type='checkbox' id='filelist-name-rev' />
-<input style='display: none' type='checkbox' id='filelist-date-rev' />
-<input style='display: none' type='checkbox' id='filelist-size-rev' />
-<script type='x'>--></script>
-<table class='filelist'>
- <thead>
- <tr>
- <th />
- <th class='name'>
- <label for='filelist-name-sort'><span>Name</span></label>
- <script type='x'><![CDATA[]]x><!--]]></script>
- <label for='filelist-name-rev' style='display: none'>
- <span>Name</span>
- <img alt='FWD' width='16' height='16' src='/images/down.svg' />
- <img alt='REV' width='16' height='16' src='/images/up.svg' style='display: none' />
- </label>
- <script type='x'>--></script>
- </th>
- <th class='date'>
- <label for='filelist-date-sort'><span>Last Modified</span></label>
- <script type='x'><![CDATA[]]x><!--]]></script>
- <label for='filelist-date-rev' style='display: none'>
- <span>Last Modified</span>
- <img alt='FWD' width='16' height='16' src='/images/down.svg' />
- <img alt='REV' width='16' height='16' src='/images/up.svg' style='display: none' />
- </label>
- <script type='x'>--></script>
- </th>
- <th class='size'>
- <label for='filelist-size-sort'><span>Size</span></label>
- <script type='x'><![CDATA[]]x><!--]]></script>
- <label for='filelist-size-rev' style='display: none'>
- <span>Size</span>
- <img alt='FWD' width='16' height='16' src='/images/down.svg' />
- <img alt='REV' width='16' height='16' src='/images/up.svg' style='display: none' />
- </label>
- <script type='x'>--></script>
- </th>
- </tr>
- </thead>
- <tbody>
-<%=
- parentrow = if files[".."] then "#{render_entry(files, "..")}" end
- files.delete("..")
- if parentrow then "<tr>#{parentrow}</tr>" end
-%>
-<%
-by_name = files.keys.sort{ |a, b| strverscmp(a, b) }
-by_name.each_index do |i|
- entry = render_entry(files, by_name[i])
- if i+1 == by_name.length
- entry.sub!(%r{(.*)</td>}m,
- "\\1<script type='x'><![CDATA[]]x><!--]]></script></td>")
- end
-%>
- <tr><%= entry %></tr>
-<% end %>
- </tbody>
-
- <tbody style='display: none'>
-<%
-def meta_cmp(files, key, a, b)
- av, bv = files[a][key], files[b][key]
- return av <=> bv if av != bv
- return strverscmp(a, b)
-end
-
-by_date = files.keys.sort { |a, b| meta_cmp(files, :sorttime, a, b) }
-by_size = files.keys.sort { |a, b| meta_cmp(files, :size, a, b) }
-
-listnames = [ "namerev", "date", "daterev", "size", "sizerev" ]
-lists = [ by_name.reverse, by_date, by_date.reverse, by_size, by_size.reverse ]
-if parentrow
-%>
- <tr class='<%= listnames.join(" ") %>'><%= parentrow %></tr>
-<%
-end
-evenmap = (0..(lists.length-1)).map { false }
-even = false
-
-while not (elems = lists.map(&:first)).compact.empty?
- matches = (0..(lists.length-1)).to_a.keep_if { |x| evenmap[x] == even }
- if !matches.empty?
- elems = elems.values_at(*matches).compact
- mode = elems.group_by{|a| a}.max{|a, b| a[1].length <=> b[1].length}[0]
- matches = []
-
- lists.each_index do |i|
- if evenmap[i] == even and lists[i].first.eql? mode
- lists[i].shift
- evenmap[i] ^= true
- evenmap[i] = nil if lists[i].empty?
-
- matches << i
- end
- end
-%>
- <tr class='<%= listnames.values_at(*matches).join(" ") %>'>
- <%= render_entry(files, mode) %>
- </tr>
-<%
- else
-%>
- <tr><td /></tr>
-<%
- end
-
- even ^= true
-end
-%>
- <tr><td><script type='x'>--></script></tr>
- </tbody>
-</table>
-</div>