瀏覽代碼

(Rough) LL generator and ID list.

scossu 2 周之前
父節點
當前提交
465b28158f
共有 2 個文件被更改,包括 78 次插入31 次删除
  1. 27 1
      pkar.lua
  2. 51 30
      src/html_generator.lua

+ 27 - 1
pkar.lua

@@ -3,7 +3,10 @@
 local cli = require "cli"
 local plpath = require "pl.path"
 
+local nsm = require "volksdata.namespace"
 local term = require "volksdata.term"
+local triple = require "volksdata.triple"
+local graph = require "volksdata.graph"
 
 local pkar = require "pocket_archive"
 local sub = require "pocket_archive.submission"
@@ -26,6 +29,17 @@ init = cli.command {
     end
 }
 
+list = cli.command {
+    "List all resource IDs.",
+
+    function()
+        local gr = graph.new(pkar.store, term.DEFAULT_CTX)
+        for _, s in pairs(gr:unique_terms(triple.POS_S)) do
+            print(nsm.denormalize_uri(s.data))
+        end
+    end,
+}
+
 deposit = cli.command {
     "Deposit a package.",
 
@@ -47,7 +61,6 @@ gen_site = cli.command {
     function(args) hgen.generate_site() end
 }
 
-
 gen_rdf = cli.command {
     "Generate an RDF representation of a resource.",
 
@@ -67,6 +80,19 @@ gen_rdf = cli.command {
     end,
 }
 
+gen_ll = cli.command {
+    "Generate a laundry list for a stored resource.",
+
+    cli.positional "id" {
+        "ID of the resource, prefixed by `par:`",
+        type = cli.string,
+    },
+
+    function(args)
+        local s = term.new_iriref_ns(args.id)
+        print(hgen.generate_ll(s))
+    end
+}
 
 cli.program {
     "Pocket Archive command line interface.",

+ 51 - 30
src/html_generator.lua

@@ -1,3 +1,4 @@
+local csv = require "ftcsv"
 local datafile = require "datafile"
 local dir = require "pl.dir"
 local etlua = require "etlua"
@@ -97,15 +98,15 @@ local function generate_dres(s, mconf)
     -- Metadata
     local attrs = gr:connections(s, term.LINK_OUTBOUND)
     for p, ots in pairs(attrs) do
-        local fname = nsm.denormalize_uri(p.data)
-        p_label = ((mconf.properties or NT)[fname] or NT).label
+        local pname = nsm.denormalize_uri(p.data)
+        p_label = ((mconf.properties or NT)[pname] or NT).label
         -- RDF types are shown in in breadcrumbs.
-        if fname == "rdf:type" then goto skip
-        elseif ((mconf.properties or NT)[fname] or NT).type == "rel" then
+        if pname == "rdf:type" then goto skip
+        elseif ((mconf.properties or NT)[pname] or NT).type == "rel" then
             -- Relationship.
-            rel[fname] = {label = p_label, uri = fname}
-            for _, o in pairs(ots) do table.insert(dmd[fname], o.data) end
-        elseif fname == "pas:first" then
+            rel[pname] = {label = p_label, uri = pname}
+            for _, o in pairs(ots) do table.insert(dmd[pname], o.data) end
+        elseif pname == "pas:first" then
             -- Build a linked list for every first found.
             for _, o in pairs(ots) do
                 -- Loop through all first children.
@@ -138,12 +139,12 @@ local function generate_dres(s, mconf)
                 end
                 table.insert(children, ll)
             end
-        elseif fname == "pas:next" then
+        elseif pname == "pas:next" then
             -- Sibling.
             for _, o in pairs(ots) do ls_next = o.data break end
         else
             -- Descriptive metadata.
-            local attr = {label = p_label, uri = fname}
+            local attr = {label = p_label, uri = pname}
             -- TODO differentiate term types
             for _, o in pairs(ots) do table.insert(attr, o.data) end
             table.sort(attr)
@@ -196,23 +197,23 @@ local function generate_ores(s, mconf)
     -- Metadata
     local attrs = gr:connections(s, term.LINK_OUTBOUND)
     for p, ots in pairs(attrs) do
-        local fname = nsm.denormalize_uri(p.data)
-        p_label = ((mconf.properties or NT)[fname] or NT).label
+        local pname = nsm.denormalize_uri(p.data)
+        p_label = ((mconf.properties or NT)[pname] or NT).label
         -- RDF types are shown in in breadcrumbs.
-        if fname == "rdf:type" then goto skip
-        elseif ((mconf.properties or NT)[fname] or NT).type == "rel" then
+        if pname == "rdf:type" then goto skip
+        elseif ((mconf.properties or NT)[pname] or NT).type == "rel" then
             -- Relationship.
-            rel[fname] = {label = p_label, uri = fname}
-            for _, o in pairs(ots) do table.insert(techmd[fname], o.data) end
-        elseif fname == "pas:next" then
+            rel[pname] = {label = p_label, uri = pname}
+            for _, o in pairs(ots) do table.insert(techmd[pname], o.data) end
+        elseif pname == "pas:next" then
             -- Sibling.
             for _, o in pairs(ots) do ls_next = o.data break end
         else
             -- Descriptive metadata.
-            techmd[fname] = {label = p_label, uri = fname}
+            techmd[pname] = {label = p_label, uri = pname}
             -- TODO differentiate term types
-            for _, o in pairs(ots) do table.insert(techmd[fname], o.data) end
-            table.sort(techmd[fname])
+            for _, o in pairs(ots) do table.insert(techmd[pname], o.data) end
+            table.sort(techmd[pname])
         end
         ::skip::
     end
@@ -262,7 +263,7 @@ local function generate_ores(s, mconf)
     out_html = templates.ores.data({
         --webroot = M.webroot,
         site_title = pkar.config.site.title or pkar.default_title,
-        fname = plpath.basename(techmd["pas:sourcePath"][1]),
+        pname = plpath.basename(techmd["pas:sourcePath"][1]),
         head_tpl = templates.head.data,
         header_tpl = templates.header.data,
         mconf = mconf,
@@ -302,10 +303,10 @@ M.generate_res_idx = function(s, mconf)
 
     local attrs = gr:connections(s, term.LINK_OUTBOUND)
 
-    local function format_value(fname, o)
-        logger:debug("Adding value to " .. fname .. ": " .. ((o or NT).data or "nil"))
+    local function format_value(pname, o)
+        logger:debug("Adding value to " .. pname .. ": " .. ((o or NT).data or "nil"))
         local v
-        if fname == "rdf:type" or fname == "pas:contentType" then
+        if pname == "rdf:type" or pname == "pas:contentType" then
             v = nsm.denormalize_uri(o.data)
         else v = o.data
         end
@@ -313,9 +314,9 @@ M.generate_res_idx = function(s, mconf)
     end
 
     for p, ots in pairs(attrs) do
-        local fname = nsm.denormalize_uri(p.data)
-        local pconf = (mconf.properties or NT)[fname] or NT
-        if idx_ignore[fname] or pconf.type == "resource" then goto skip end
+        local pname = nsm.denormalize_uri(p.data)
+        local pconf = (mconf.properties or NT)[pname] or NT
+        if idx_ignore[pname] or pconf.type == "resource" then goto skip end
 
         local attr
         -- Quick check if it's multi-valued
@@ -323,15 +324,15 @@ M.generate_res_idx = function(s, mconf)
         if next(ots, next(ots)) then
             attr = {}
             for _, o in pairs(ots) do
-                table.insert(attr, format_value(fname, o))
+                table.insert(attr, format_value(pname, o))
             end
         else
             _, o = next(ots)
-            attr = format_value(fname, o)
+            attr = format_value(pname, o)
         end
 
-        rrep[pconf.label or fname] = attr  -- Add to search index.
-        idx_keys[fname] = true  -- Add to search keys.
+        rrep[pconf.label or pname] = attr  -- Add to search index.
+        idx_keys[pname] = true  -- Add to search keys.
         ::skip::
     end
     return rrep
@@ -348,6 +349,26 @@ end
 
 M.generate_ll = function(s)
     local res_gr = M.get_graph(s)
+    tdata = {}
+    for p, ots in pairs(res_gr:connections(s, term.LINK_OUTBOUND)) do
+        pname = nsm.denormalize_uri(p.data)
+        for _, o in pairs (ots) do
+            -- Find a row where the pname slot has not been occupied.
+            for i = 1, math.huge do
+                if (tdata[i] or NT)[pname] then goto continue
+                else
+                    if tdata[i] then tdata[i][pname] = o.data
+                    else tdata[i] = {[pname] = o.data} end
+                    break
+                end
+                ::continue::
+            end
+        end
+    end
+    -- FIXME ftcsv encodes nil values as `"nil"`. See
+    -- https://github.com/FourierTransformer/ftcsv/issues/46
+
+    return csv.encode(tdata)
 end