From 0b2482e6f67145faa95bceadcf14811153ca9a7f Mon Sep 17 00:00:00 2001
From: Matt Heffron
Date: Tue, 15 Apr 2025 11:00:33 -0700
Subject: [PATCH 01/23] Initial attempt to create individual pages for the
Bibliography entries. 1. The "main" Bibliography page is not (yet) modified
to reference these. 2. This fails when hugo tries to render the html for the
generated .md files.
The error from Hugo (it reports 4 then seems to hang):
ERROR render of "/home/matt/Interlisp/Interlisp.github.io/content/en/history/bibliography/2LJ5ITDD.md" failed: "/home/matt/.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/google/docsy@v0.10.0/layouts/docs/single.html:2:3": execute of template failed: template: docs/single.html:2:3: executing "main" at <.Render>: error calling Render: failed to execute template content.html: "/home/matt/.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/google/docsy@v0.10.0/layouts/_default/content.html:10:4": execute of template failed: template: content.html:10:4: executing "content.html" at <.Content>: error calling Content: "/home/matt/Interlisp/Interlisp.github.io/content/en/history/bibliography/2LJ5ITDD.md:8:1": failed to render shortcode "bibItem": failed to process shortcode: "/home/matt/Interlisp/Interlisp.github.io/layouts/shortcodes/bibItem.html:168:23": execute of template failed: template: _shortcodes/bibitem.html:168:23: executing "_shortcodes/bibitem.html" at <.params.bibItem>: can't evaluate field params in type *hugolib.ShortcodeWithPage
---
layouts/shortcodes/bibItem.html | 232 ++++++++++++++++++++++++++++++++
scripts/bib-fns.jq | 4 +
scripts/bibSplit.pl | 29 ++++
scripts/update_bibliography.sh | 195 +++++++++++++++++++--------
4 files changed, 405 insertions(+), 55 deletions(-)
create mode 100644 layouts/shortcodes/bibItem.html
create mode 100644 scripts/bibSplit.pl
diff --git a/layouts/shortcodes/bibItem.html b/layouts/shortcodes/bibItem.html
new file mode 100644
index 00000000..0397ee4c
--- /dev/null
+++ b/layouts/shortcodes/bibItem.html
@@ -0,0 +1,232 @@
+
+
+{{ $notesIcon := "\u24C3" }}
+{{ $nonBreakingHyphen := "\u2011" }}
+
+
+
+
+
+ Reference
+
+
+
+ {{ with .params.bibItem }}
+
+ {{ $itemID := (cond (gt (len .id) 0) (replace .id `/` `_`) `_0`) }}
+
+ {{ if or .author .editor }}{{ if not .author }}Edited by: {{ end }}{{ range $naE, $auEd := or .author .editor }}{{ if $naE }}; {{ end }}{{ if $auEd.literal }}{{ $auEd.literal }}{{ else if and $auEd.family $auEd.given }}{{ $auEd.family }}, {{ $auEd.given }}{{ else }}{{ $auEd.family }}{{ $auEd.given }}{{ end }}{{ end }}
+
{{ end }}
+ {{ if .abstract }}AAA {{ end }}
+ {{ if and false .note }}
+ {{ $notes := split (plainify .note) "\n" }}
+ Notes
+
+ {{ range $nn, $note := $notes }}
+ {{if strings.ContainsNonSpace $note }}
+ {{ if $nn }} {{ end }}
+ {{ print (safeJS (replace (replace (htmlUnescape $note) "-" $nonBreakingHyphen) " " " ")) }}
+ {{ end }}
+ {{ end }}
+ {{ end }}
+ {{ if .abstract }}
+ {{ range $na, $abstract := split (plainify .abstract) "\n" }}
+ {{if strings.ContainsNonSpace $abstract }}
+ {{ if $na }} {{ end }}
+ {{ $trimmed := strings.TrimLeft " " $abstract }}{{ $indent := (sub ($abstract | len) ($trimmed | len)) }}
+ {{ print (safeJS (htmlUnescape (printf "%s" $trimmed | printf "%s%s" (strings.Repeat $indent " ") | printf "%s"))) }}
+ {{ end }}
+ {{ end }}
+
{{ end }}
+
+ {{ end }}
+
+
+
+
+
diff --git a/scripts/bib-fns.jq b/scripts/bib-fns.jq
index ae61d919..839a1dc6 100644
--- a/scripts/bib-fns.jq
+++ b/scripts/bib-fns.jq
@@ -90,3 +90,7 @@ def semiflatten: # assumes that only one item is the input
+ ($innerKeys | map(. as $iKey | {"key": $iKey, "value": ($inner | getpath([$iKey]))})) )
| from_entries;
+def bibItem: # assumes that only one item is the input
+ . as $item
+ | (keys - ["key","title","target"]) as $tailKeys
+ | {"key": .key, "title": .title, "target": .target } + ($tailKeys | map(. as $tKey | {"key": $tKey, "value": ($item | getpath([$tKey]))}) | from_entries);
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
new file mode 100644
index 00000000..d64c5410
--- /dev/null
+++ b/scripts/bibSplit.pl
@@ -0,0 +1,29 @@
+#! /usr/bin/perl -n
+BEGIN { $bibDir = $ENV{'BIBLIOGRAPHY_DIR'}; print "bibDir: $bibDir\n";}
+my $item = $_;
+/"key"\:"([A-Za-z0-9]{8})"/ || print "Cannot find key on line: $_\n";
+my $key = $1;
+/"title"\:("(?:[^"\\]++|\\.)*+")/ || print "Cannot find title for key \"$key\" on line: $_\n";
+my $itemTitle = $1;
+/"target"\:"([A-Za-z0-9]{8})"/ || print "Cannot find target for key \"$key\" on line: $_\n";
+my $target = $1;
+if ($key eq $target) { # only top level entries
+ # print "KEY: $key TITLE:$itemTitle\n";
+ my $handle = undef;
+ my $itemfn = "$bibDir/$key.md";
+ open($handle, ">", $itemfn) || die "$0: cannot open $itemfn in write-open mode: $!";
+ print $handle <}}
+ENDITEM
+ close $handle || die "$0: close of file $itemfn failed: $!";
+}
+else
+{
+ # print "KEY: $key TARGET: $target TITLE:$itemTitle\n";
+}
diff --git a/scripts/update_bibliography.sh b/scripts/update_bibliography.sh
index 6b99a005..7b73b48a 100755
--- a/scripts/update_bibliography.sh
+++ b/scripts/update_bibliography.sh
@@ -2,13 +2,37 @@
set -e
-rawItemsFile=false
-debugFiles=false
+rawItemsFile=true
+debugFiles=true
tagFiles=false
typeFiles=false
+curlFiles=false
# The collection files will be created only if directly querying Zotero API.
collectionFiles=false
+# removeChildrenFromFinalFile=false
+
+showInfoLevel=2
+# 0: NO showInfo messages.
+# 1: high level general info messages.
+# 2: warning-type messages.
+# 3:
+# 4:
+# 5: detailed general info messages.
+# 6:
+# 7:
+# 8: individual processing steps (most of which may generate a debug File -- see $debugFiles)
+# 9: very detailed general info messages.
+# 10: extremely detailed messages (e.g., calls to curl, etc.)
+
+function showInfo() {
+ # The $1 is the level for this message ($showInfoLevel must be >= this)
+ # The $2 is the message string
+ if [[ $showInfoLevel -ge $1 ]] ; then
+ echo "$2"
+ fi
+}
+
dfn="00"
function debugFileName() {
# The $1 is the file NAME string (without the number prefix or extension)
@@ -27,45 +51,76 @@ collections=""
function add_items_from_collection () {
local collection_key="$1"
- echo "Getting collection $collection_key"
+ local collection_item=$(jq -r "map(select(.key==\"$collection_key\"))|.[0]" <<< "$collections")
+ showInfo 5 "====================================="
+ showInfo 5 "collection_item: $collection_item"
+ local collection_name=$(jq -r '.name' <<< "$collection_item")
+ local deleted=$(jq -r '.deleted // false' <<< "$collection_item")
+ showInfo 5 "collection.deleted: $deleted"
+ local numItems=$(jq -r '.numItems' <<< "$collection_item")
+ if [[ $deleted = "true" ]] ; then
+ showInfo 2 "Skipping deleted collection $collection_key: $collection_name"
+ return
+ elif [[ numItems -eq 0 ]] ; then
+ showInfo 2 "Empty collection $collection_key: $collection_name"
+ else
+ showInfo 1 "Getting collection $collection_key: $collection_name"
local start=0
local limit=100
while :; do
+ showInfo 10 "curl of $collection_key at start $start"
local this_page=$(curl -s "https://api.zotero.org/groups/$GROUP_ID/collections/$collection_key/items?include=data,csljson&start=$start&limit=$limit&v=3")
+ local item_count=$(jq '. | length' <<< "$this_page")
+ showInfo 10 "curl returned $item_count items"
+ if [[ $item_count > 0 ]] ; then
+ if $curlFiles ; then
+ local pageFile=$( printf "curl/%s-%02d.json" $collection_key $(( $start / $limit )) )
+ echo "$this_page" > "$pageFile"
+ fi
items=$(jq -s 'add' <<< "$this_page$items")
- start=$(($start + $limit))
-
- # Break when we don't get any more items
- [[ $(jq '. | length' <<< "$this_page") > 0 ]] || break
+ showInfo 10 "items updated"
+ start=$(($start + $item_count))
+ fi
+ # Break when we don't get the full $limit of items
+ # (it's still possible to do one redundant curl if collection has exact multiple of $limit items)
+ [[ $item_count -ge $limit ]] || break
done
+ fi
- local subcollections=$(curl -s "https://api.zotero.org/groups/$GROUP_ID/collections/$collection_key/collections" | jq -r '.[].data|{key, name, parentCollection}' | jq -s '.')
- collections=$(jq -s 'add' <<< "$subcollections$collections")
+ local numCollections=$(jq -r '.numCollections' <<< "$collection_item")
+ if [[ $numCollections -gt 0 ]] ; then
+ showInfo 5 "Getting subcollections of $collection_key: $collection_name"
+ local subcollections=$(curl -s "https://api.zotero.org/groups/$GROUP_ID/collections/$collection_key/collections" | jq -r 'map(.data+.meta)')
+ collections=$(jq -s 'add' <<< "$collections$subcollections")
# Recurse into subcollections
while read subcollection_key; do
add_items_from_collection $subcollection_key
done < <(jq -r '.[].key' <<< "$subcollections")
+ fi
}
root_collection="FSK5IX4F"
if [[ $# -eq 0 ]] ; then
# Initialize with the root collection.
- collections=$(curl -s "https://api.zotero.org/groups/$GROUP_ID/collections/top" | jq -r '.[].data|{key, name, parentCollection}' | jq -s '.' | jq "map(select(.key==\"$root_collection\"))")
+ collections=$(curl -s "https://api.zotero.org/groups/$GROUP_ID/collections/$root_collection" | jq -s -r 'map(.data+.meta)')
add_items_from_collection $root_collection
if $collectionFiles ; then
echo "$collections" > collections.json
fi
- echo "$(jq '. | length' <<< "$collections") collections"
+ showInfo 1 "$(jq '. | length' <<< "$collections") collections"
while read neededUrl; do
+ showInfo 10 "curl of $neededUrl"
item=$(curl -s "$neededUrl?include=data,csljson&v=3")
+ showInfo 10 "curl returned"
items=$(jq -s 'add' <<< "[$item]$items")
+ showInfo 10 "items updated"
done < <(jq -r 'include "./bib-fns";getNeededUrls|.[]' <<< "$items")
+ if $collectionFiles ; then
grouped_collections=$(jq 'group_by(.parentCollection)' <<< "$collections")
# This is not yet fully hierarchically nested.
- if $collectionFiles ; then
echo "$grouped_collections" > grouped_collections.json
fi
# Only if we got the raw items from the Zotero API
@@ -76,29 +131,44 @@ else
items=$(<$1)
fi
-echo "Got $(jq '. | length' <<< "$items") items"
+showInfo 1 "Got $(jq '. | length' <<< "$items") items"
# Piece-wise processing for debugging:
items=$(jq 'include "./bib-fns";map(semiflatten)' <<< "$items")
+showInfo 8 "Elevate fields in .csljson and .data to the item level."
if $debugFiles ; then
dfn=$(debugFileName "semiflattened" $dfn)
echo "$items" > "$dfn"
fi
items=$(jq 'include "./bib-fns";map(if has("note") then .note |= unwrapDiv else . end)' <<< "$items")
+showInfo 8 "Clean up note field (extract from HTML div)."
if $debugFiles ; then
dfn=$(debugFileName "cleanDiv" $dfn)
echo "$items" > "$dfn"
fi
-#find and eliminate duplicate .key entries
+
+showInfo 5 "Delete items that Zotero indicated as such."
+beforeCount=$(jq '. | length' <<< "$items")
+items=$(jq 'map(select(.deleted|not))' <<< "$items")
+afterCount=$(jq '. | length' <<< "$items")
+showInfo 5 "Removed $(( $beforeCount - $afterCount )) items marked as deleted."
+
+showInfo 8 "Find duplicate .key entries"
groupedByKey=$(jq 'group_by(.key)' <<< "$items")
if $debugFiles ; then
dupIDs=$(jq 'map(select(length>1) | {key: .[0].key, items: .})' <<< "$groupedByKey")
+ numDupKeys=$(jq '. | length' <<< "$dupIDs")
+ if [[ "$numDupKeys" -ne 0 ]] ; then
+ numDupEntries=$(jq 'map(.items | length) | add' <<< "$dupIDs")
+ showInfo 2 "$numDupKeys keys have multiple occurrences totalling $numDupEntries entries"
+ fi
dfn=$(debugFileName "dupIDs" $dfn)
echo "$dupIDs" > "$dfn"
fi
#remove duplicates
items=$(jq 'map(.[0]) | sort_by(.date)' <<< "$groupedByKey")
+showInfo 8 "Remove Duplicates"
if $debugFiles ; then
dfn=$(debugFileName "noDupSorted" $dfn)
echo "$items" > "$dfn"
@@ -115,50 +185,60 @@ if $tagFiles ; then
fi
# consolidate URL into url field
items=$(jq 'include "./bib-fns";map(if nonBlankKey("URL") then setpath(["url"]; .URL) | del(.URL) else . end)' <<< "$items")
+showInfo 8 "Consolidate URL to url (upper vs. lower case)"
if $debugFiles ; then
- dfn=$(debugFileName "consolidated" $dfn)
+ dfn=$(debugFileName "urlConsolidated" $dfn)
echo "$items" > "$dfn"
fi
# Use DOI to create url where needed and available
items=$(jq 'include "./bib-fns";map(if (blankKey("url") and nonBlankKey("DOI")) then setpath(["url"]; make_DOI_to_url(.DOI)) else . end)' <<< "$items")
+showInfo 8 "Use DOI to construct URL if needed"
if $debugFiles ; then
dfn=$(debugFileName "DOI-url" $dfn)
echo "$items" > "$dfn"
fi
items=$(jq 'include "./bib-fns";map(getTargetInfo)' <<< "$items")
-if $debugFiles ; then
- dfn=$(debugFileName "withTargetInfo" $dfn)
- echo "$items" > "$dfn"
-fi
# now use children items to amend the info for the parentItem
-allFixupInfo=$(jq 'group_by(.target)|map(sort_by(.parentItem))' <<< "$items")
+childrenGroupedByParent=$(jq 'group_by(.target)|map(sort_by(.parentItem))' <<< "$items")
+showInfo 8 "Collect children grouped by parent"
if $debugFiles ; then
- dfn=$(debugFileName "allFixupInfo" $dfn)
- echo "$allFixupInfo" > "$dfn"
+ dfn=$(debugFileName "childrenGroupedByParent" $dfn)
+ echo "$childrenGroupedByParent" > "$dfn"
fi
-# embed children into their parentItem (children field). Then delete items that Zotero indicated as such.
-items=$(jq 'map(if has(1) then (first + {children: .[1:]}) else first end)|map(select(.deleted|not))' <<< "$allFixupInfo")
+
+showInfo 8 "Embed Children into their parentItem (children field)."
+items=$(jq 'map(if has(1) then (first + {children: .[1:]}) else first end)' <<< "$childrenGroupedByParent")
if $debugFiles ; then
- dfn=$(debugFileName "itemsNestedChildren" $dfn)
+ dfn=$(debugFileName "itemsWithNestedChildren" $dfn)
echo "$items" > "$dfn"
fi
-echo "Got $(jq '. | length' <<< "$items") clean, top-level items"
+showInfo 1 "Got $(jq '. | length' <<< "$items") clean, top-level items"
items=$(jq 'include "./bib-fns";map(applyChildrenAmendments)' <<< "$items")
+showInfo 8 "Update Parent items from their Children"
if $debugFiles ; then
- dfn=$(debugFileName "updatedItems" $dfn)
+ dfn=$(debugFileName "updatedItemsFromChildren" $dfn)
echo "$items" > "$dfn"
fi
absNote=$(jq 'include "./bib-fns";map(select((nonBlankKey("abstract") or nonBlankKey("abstractNote")) and (.abstract != .abstractNote)) | {key: .key, title: .title, abstract: .abstract, abstractNote: .abstractNote})' <<< "$items")
+showInfo 8 "Check abstract vs. abstractNote mismatch"
if $debugFiles ; then
dfn=$(debugFileName "absNoteMismatch" $dfn)
echo "$absNote" > "$dfn"
fi
+absNoteMismatchCount=$(jq '. | length' <<< "$absNote")
+if [[ "$absNoteMismatchCount" -eq 1 ]] ; then
+ showInfo 2 "Warn: 1 entry with mismatch between abstract and abstractNote fields"
+elif [[ "$absNoteMismatchCount" -ne 0 ]] ; then
+ showInfo 2 "Warn: $absNoteMismatchCount entries with mismatch between abstract and abstractNote fields"
+fi
+
# remove redundant .abstractNote fields
items=$(jq 'include "./bib-fns";map(cleanAbstracts)' <<< "$items")
+showInfo 8 "Remove redundant abstractNote fields"
if $debugFiles ; then
dfn=$(debugFileName "abstractsCleaned" $dfn)
echo "$items" > "$dfn"
@@ -167,51 +247,56 @@ if $typeFiles ; then
types=$(jq 'map({key, title, type, itemType}) | group_by(.type) | map({type:.[0].type, itemTypes:(group_by(.itemType)|map({itemType:.[0].itemType, items:map({title, key})}))})' <<<"$items")
echo "$types" > finalTitleKeyTypeInfo.json
fi
-noURL=$(jq 'include "./bib-fns";map(select(blankKey("url")))' <<< "$items")
if $debugFiles ; then
+ noURL=$(jq 'include "./bib-fns";map(select(blankKey("url")))' <<< "$items")
dfn=$(debugFileName "noURL" $dfn)
echo "$noURL" > "$dfn"
fi
finalCount=$(jq '. | length' <<< "$items")
-# # Remove .children arrays, if any. Save space.
-# items=$(jq 'map(del(.children))' <<< "$items")
-# if $debugFiles ; then
- # dfn=$(debugFileName "withoutChildrenArray")
- # echo "$items" > "$dfn"
+
+# if $removeChildrenFromFinalFile; then
+# # Remove .children arrays, if any. Save space.
+# items=$(jq 'map(del(.children))' <<< "$items")
+# showInfo 8 "Remove .children arrays from final items"
+# if $debugFiles ; then
+# dfn=$(debugFileName "withoutChildrenArray" $dfn)
+# echo "$items" > "$dfn"
+# fi
# fi
-# Group by year
-items=$(jq 'group_by(.issued."date-parts"[0][0])' <<< "$items")
+
+# Remove library, links, and meta objects from entries
+# (These are not used any further on, so simplify.)
+items=$(jq 'map(del(.["library", "links", "meta"]))' <<< "$items")
+showInfo 8 "Remove library, links, and meta objects"
if $debugFiles ; then
- dfn=$(debugFileName "grouped" $dfn)
+ dfn=$(debugFileName "noLibraryLinksMeta" $dfn)
echo "$items" > "$dfn"
fi
+# Do this here, instead of keeping a copy of the current value of $items, just to do this later.
+jq -c 'include "./bib-fns";.[] | bibItem' <<< "$items" > bibliography-items-by-line.json
+
+# Group by year
+items=$(jq 'group_by(.issued."date-parts"[0][0])' <<< "$items")
items=$(jq 'map({ (.[0].issued."date-parts"[0][0] // "Undated" | tostring): . })' <<< "$items")
+showInfo 8 "Group by year"
if $debugFiles ; then
- dfn=$(debugFileName "Undated" $dfn)
- echo "$items" > "$dfn"
-fi
-items=$(jq 'map(to_entries)' <<< "$items")
-if $debugFiles ; then
- dfn=$(debugFileName "entries" $dfn)
- echo "$items" > "$dfn"
-fi
-items=$(jq 'flatten(1)' <<< "$items")
-if $debugFiles ; then
- dfn=$(debugFileName "flattened" $dfn)
+ dfn=$(debugFileName "groupedByYear" $dfn)
echo "$items" > "$dfn"
fi
-items=$(jq 'group_by(.key)' <<< "$items")
-if $debugFiles ; then
- dfn=$(debugFileName "groupedByKey" $dfn)
- echo "$items" > "$dfn"
-fi
-items=$(jq 'include "./bib-fns";map(reconstituteGroupedEntries) | from_entries' <<< "$items")
+
+items=$(jq 'include "./bib-fns";map(to_entries) | flatten(1) | group_by(.key) | map(reconstituteGroupedEntries) | from_entries' <<< "$items")
if $debugFiles ; then
dfn=$(debugFileName "final" $dfn)
echo "$items" > "$dfn"
fi
+showInfo 1 "Generating individual Bibliography entries' .md files"
+BIBLIOGRAPHY_DIR="$(dirname "$0")/../content/en/history/bibliography"
+export BIBLIOGRAPHY_DIR
+./bibSplit.pl bibliography-items-by-line.json
+# Cleanup (uncomment once working)
+# rm bibliography-items-by-line.json
-echo "Outputting CSL JSON"
-echo "$finalCount entries"
+showInfo 1 "Outputting CSL JSON"
+showInfo 1 "$finalCount entries"
echo "$items" > "$(dirname "$0")/../static/data/bibliography.json"
From f212723cf5f587a864663ec77077a9abc54369d7 Mon Sep 17 00:00:00 2001
From: Matt Heffron
Date: Wed, 16 Apr 2025 09:52:29 -0700
Subject: [PATCH 02/23] Improved, but still work in progress. This now creates
the files but has some difficulties. The main Bibliography page hasn't been
changed.
---
.gitignore | 1 +
layouts/shortcodes/bibItem.html | 174 ++++++++++++++++++++++----------
scripts/bib-fns.jq | 3 +
scripts/bibSplit.pl | 44 ++++----
scripts/update_bibliography.sh | 38 ++++---
static/data/bibItems/.gitkeep | 0
6 files changed, 169 insertions(+), 91 deletions(-)
create mode 100644 static/data/bibItems/.gitkeep
diff --git a/.gitignore b/.gitignore
index b41f2aa3..5a668c00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ _gen/
.hugo_build.lock
.idea
data/bibliography.json
+/docs
diff --git a/layouts/shortcodes/bibItem.html b/layouts/shortcodes/bibItem.html
index 0397ee4c..82085b92 100644
--- a/layouts/shortcodes/bibItem.html
+++ b/layouts/shortcodes/bibItem.html
@@ -14,10 +14,7 @@
.abstractContent {
padding: 5px;
margin: 0 5px 0 15px;
- display: none;
- font-size: 0.9rem;
- overflow: hidden;
- background-color: #e8e8ff;
+ font-size: 1.0rem;
clear: both;
}
@@ -30,12 +27,6 @@
color: white;
}
-.bibTitle {
- font-weight: 700;
-}
-
-.authors { margin: 5px auto 2px 5px; }
-
.tooltipNotes {
position: relative;
display: inline-block;
@@ -145,58 +136,129 @@
border-color: #555 transparent transparent transparent;
}
+.label {
+ font-weight: 700;
+}
+
-{{ $notesIcon := "\u24C3" }}
-{{ $nonBreakingHyphen := "\u2011" }}
+{{- $notesIcon := "\u24C3" -}}
+{{- $nonBreakingHyphen := "\u2011" -}}
-/*
-var abstractExpanderOpen = "Abstract +";
-var abstractExpanderClose = "Abstract -";
-*/
-
-
-
-
- Reference
-
-
-
- {{ with .params.bibItem }}
-
- {{ $itemID := (cond (gt (len .id) 0) (replace .id `/` `_`) `_0`) }}
-
- {{ if or .author .editor }}{{ if not .author }}Edited by: {{ end }}{{ range $naE, $auEd := or .author .editor }}{{ if $naE }}; {{ end }}{{ if $auEd.literal }}{{ $auEd.literal }}{{ else if and $auEd.family $auEd.given }}{{ $auEd.family }}, {{ $auEd.given }}{{ else }}{{ $auEd.family }}{{ $auEd.given }}{{ end }}{{ end }}
-
{{ end }}
- {{ if .abstract }}AAA {{ end }}
- {{ if and false .note }}
- {{ $notes := split (plainify .note) "\n" }}
- Notes
-
- {{ range $nn, $note := $notes }}
- {{if strings.ContainsNonSpace $note }}
- {{ if $nn }} {{ end }}
- {{ print (safeJS (replace (replace (htmlUnescape $note) "-" $nonBreakingHyphen) " " " ")) }}
- {{ end }}
- {{ end }}
- {{ end }}
- {{ if .abstract }}
- {{ range $na, $abstract := split (plainify .abstract) "\n" }}
- {{if strings.ContainsNonSpace $abstract }}
- {{ if $na }} {{ end }}
- {{ $trimmed := strings.TrimLeft " " $abstract }}{{ $indent := (sub ($abstract | len) ($trimmed | len)) }}
- {{ print (safeJS (htmlUnescape (printf "%s" $trimmed | printf "%s%s" (strings.Repeat $indent " ") | printf "%s"))) }}
- {{ end }}
- {{ end }}
-
{{ end }}
-
- {{ end }}
-
-
-
+{{ $item := dict -}}
+{{- $jsonFile := printf "data/bibItems/%s.json" (.Get "key") -}}
+{{- $bib := resources.Get $jsonFile -}}
+{{- with $bib -}}
+ {{- with . | transform.Unmarshal -}}
+ {{- $item = . -}}
+ {{- end -}}
+{{- else -}}
+ {{- $jsonFile | errorf "Unable to get item resource '%s'" -}}
+{{- end -}}
+{{- with $item -}}
+ {{- if or .author .editor -}}
+
+ {{- if not .author -}}Edited by: {{- end -}}
+ {{- range $naE, $auEd := or .author .editor -}}
+ {{- if $naE -}}; {{ end -}}
+ {{- if $auEd.literal -}}
+ {{- $auEd.literal -}}
+ {{- else if and $auEd.family $auEd.given -}}
+ {{- $auEd.family -}}, {{- $auEd.given -}}
+ {{- else -}}
+ {{- $auEd.family -}}{{- $auEd.given -}}
+ {{- end -}}
+ {{- end -}}
+
+ {{- end -}}
+ {{- if .url }}
+
+ {{ end -}}
+ {{- if eq .itemType "journalArticle" -}}
+ {{- $journalTitle := or .publicationTitle .journalAbbreviation -}}
+ {{- if $journalTitle }}
+Publication: {{ $journalTitle -}}
+ {{- end -}}
+ {{- if .volume }}
+Volume: {{ .volume -}}
+ {{- end -}}
+ {{- if .issue }}
+Issue: {{ .issue -}}
+ {{- end -}}
+ {{- $date := "" -}}
+ {{- if .issuedDateParts -}}
+ {{- $dp := .issuedDateParts -}}
+ {{- $dpl := len $dp -}}
+ {{- $dpf := "January 1, 1900" -}}
+ {{- $y := 0 -}}
+ {{- $m := 10 -}}
+ {{- $d := 18 -}}
+ {{- if ge $dpl 1 -}}
+ {{- $y := strings.TrimLeft "0" (string (index $dp 0)) | int -}}
+ {{- $dpf := "1900" -}}
+ {{- end -}}
+ {{- if ge $dpl 2 -}}
+ {{- $m := strings.TrimLeft "0" (string (index $dp 1)) | int -}}
+ {{- $dpf := "January 1900" -}}
+ {{- end -}}
+ {{- if ge $dpl 3 -}}
+ {{- $d := strings.TrimLeft "0" (string (index $dp 2)) | int -}}
+ {{- $dpf := "January 1, 1900" -}}
+ {{- end -}}
+ {{- if $y -}}
+ {{- $t := printf "%4d-%2d-%2d" $y $m $d -}}
+ {{- $dp := time.AsTime $t -}}
+ {{- $date := $dp.Format $dpf -}}
+ {{- end -}}
+ {{- end -}}
+ {{- if and (not $date) .date -}}
+ {{- $date := .date -}}
+ {{- end -}}
+ {{- if $date }}
+Date: {{ $date -}}
+ {{- end -}}
+ {{- $pages := or .pages .page -}}
+ {{- if $pages }}
+Pages: {{ $pages -}}
+ {{- end -}}
+ {{- end -}}
+ {{- if .DOI }}
+DOI: {{ .DOI -}}
+ {{- end -}}
+ {{- if .ISSN }}
+ISSN: {{ .ISSN -}}
+ {{- end -}}
+ {{- if .abstract }}
+Abstract:
+ {{- range $na, $abstract := split (plainify .abstract) "\n" -}}
+ {{- if $na -}} {{- end -}}
+ {{if strings.ContainsNonSpace $abstract -}}
+ {{- $trimmed := strings.TrimLeft " " $abstract -}}{{- $indent := (sub ($abstract | len) ($trimmed | len)) -}}
+ {{- print (safeJS (htmlUnescape (printf "%s" $trimmed | printf "%s%s" (strings.Repeat $indent " ") | printf "%s"))) -}}
+ {{- end -}}
+ {{- end -}}
+
+ {{ end -}}
+ {{- if and false .note -}}
+ {{- $itemID := (cond (gt (len .id) 0) (replace .id `/` `_`) `_0`) -}}
+ {{- $notes := split (plainify .note) "\n" -}}
+ Notes
+
+ {{- range $nn, $note := $notes -}}
+ {{if strings.ContainsNonSpace $note -}}
+ {{- if $nn -}} {{- end -}}
+ {{- print (safeJS (replace (replace (htmlUnescape $note) "-" $nonBreakingHyphen) " " " ")) -}}
+ {{- end -}}
+ {{- end -}}
+
+
+ {{- end -}}
+{{- end -}}
+
-->
+
{{range .Site.Params.custom_css -}}
{{- end}}
diff --git a/static/js/publications.js b/static/js/publications.js
new file mode 100644
index 00000000..7fbdbbfb
--- /dev/null
+++ b/static/js/publications.js
@@ -0,0 +1,166 @@
+/*
+ * This file originates from the Wowchemy project.
+ */
+
+/*************************************************
+ * Hugo Blox Builder
+ * https://github.com/HugoBlox/hugo-blox-builder
+ *
+ * Hugo Blox Builder Publications
+ **************************************************/
+
+// Active publication filters.
+let pubFilters = {};
+
+// Search term.
+let searchRegex;
+
+// Filter values (concatenated).
+let filterValues;
+
+// Publication container.
+let $grid_pubs = $('#container-publications');
+
+// Initialise Isotope publication layout if required.
+if ($grid_pubs.length) {
+ $grid_pubs.isotope({
+ itemSelector: '.isotope-item',
+ percentPosition: true,
+ masonry: {
+ // Use Bootstrap compatible grid layout.
+ columnWidth: '.grid-sizer',
+ },
+ filter: function () {
+ let $this = $(this);
+ let searchResults = searchRegex ? $this.text().match(searchRegex) : true;
+ let filterResults = filterValues ? $this.is(filterValues) : true;
+ return searchResults && filterResults;
+ },
+ });
+
+ // Filter by search term.
+ let $quickSearch = $('.filter-search').keyup(
+ debounce(function () {
+ searchRegex = new RegExp($quickSearch.val(), 'gi');
+ $grid_pubs.isotope();
+ }),
+ );
+
+ $('.pub-filters').on('change', function () {
+ let $this = $(this);
+
+ // Get group key.
+ let filterGroup = $this[0].getAttribute('data-filter-group');
+
+ // Set filter for group.
+ pubFilters[filterGroup] = this.value;
+
+ // Combine filters.
+ filterValues = concatValues(pubFilters);
+
+ // Activate filters.
+ $grid_pubs.isotope();
+
+ // If filtering by publication type, update the URL hash to enable direct linking to results.
+ if (filterGroup === 'pubtype') {
+ // Set hash URL to current filter.
+ let url = $(this).val();
+ if (url.substr(0, 9) === '.pubtype-') {
+ window.location.hash = url.substr(9);
+ } else {
+ window.location.hash = '';
+ }
+ }
+ });
+}
+
+// Debounce input to prevent spamming filter requests.
+function debounce(fn, threshold) {
+ let timeout;
+ threshold = threshold || 100;
+ return function debounced() {
+ clearTimeout(timeout);
+ let args = arguments;
+ let _this = this;
+
+ function delayed() {
+ fn.apply(_this, args);
+ }
+
+ timeout = setTimeout(delayed, threshold);
+ };
+}
+
+// Flatten object by concatenating values.
+function concatValues(obj) {
+ let value = '';
+ for (let prop in obj) {
+ value += obj[prop];
+ }
+ return value;
+}
+
+// Filter publications according to hash in URL.
+function filter_publications() {
+ // Check for Isotope publication layout.
+ if (!$grid_pubs.length) return;
+
+ let urlHash = window.location.hash.replace('#', '');
+ let filterValue = '*';
+
+ // Check if hash is set.
+ if (urlHash != '') {
+ filterValue = '.pubtype-' + urlHash;
+ }
+
+ // Set filter.
+ let filterGroup = 'pubtype';
+ pubFilters[filterGroup] = filterValue;
+ filterValues = concatValues(pubFilters);
+
+ // Activate filters.
+ $grid_pubs.isotope();
+
+ // Set selected option.
+ $('.pubtype-select').val(filterValue);
+}
+
+document.addEventListener('DOMContentLoaded', function () {
+ // Enable publication filter for publication index page.
+ if ($('.pub-filters-select')) {
+ filter_publications();
+ // Useful for changing hash manually (e.g. in development):
+ // window.addEventListener('hashchange', filter_publications, false);
+ }
+
+ // Load citation modal on 'Cite' click.
+ $('.js-cite-modal').click(function (e) {
+ e.preventDefault();
+ let filename = $(this).attr('data-filename');
+ let modal = $('#modal');
+ modal.find('.modal-body code').load(filename, function (response, status, xhr) {
+ if (status == 'error') {
+ let msg = 'Error: ';
+ $('#modal-error').html(msg + xhr.status + ' ' + xhr.statusText);
+ } else {
+ $('.js-download-cite').attr('href', filename);
+ }
+ });
+ modal.modal('show');
+ });
+
+ // Copy citation text on 'Copy' click.
+ $('.js-copy-cite').click(function (e) {
+ e.preventDefault();
+ // Get text to copy.
+ let citation = document.querySelector('#modal .modal-body code').innerHTML;
+ navigator.clipboard
+ .writeText(citation)
+ .then(function () {
+ console.debug('Citation copied!');
+ })
+ .catch(function () {
+ console.error('Citation copy failed!');
+ });
+ });
+});
From cc2c0efe924c10d9062d0b6eef55b3eec1a2ae45 Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Thu, 21 Aug 2025 07:06:37 -0400
Subject: [PATCH 07/23] Bibliography WIP
Crude listing generated in /pulications folder.
---
go.mod | 2 +-
go.sum | 9 ++++-----
layouts/publications/list.html | 13 +++++++++++++
3 files changed, 18 insertions(+), 6 deletions(-)
create mode 100644 layouts/publications/list.html
diff --git a/go.mod b/go.mod
index b96314da..ee9a5f6c 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,6 @@ module github.com/Interlisp/Interlisp.github.io
go 1.20
require (
- github.com/google/docsy v0.10.0 // indirect
+ github.com/google/docsy v0.12.0 // indirect
github.com/google/docsy/dependencies v0.7.2 // indirect
)
diff --git a/go.sum b/go.sum
index 22e30c37..b4841ac6 100644
--- a/go.sum
+++ b/go.sum
@@ -1,13 +1,12 @@
github.com/FortAwesome/Font-Awesome v0.0.0-20230327165841-0698449d50f2/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo=
github.com/FortAwesome/Font-Awesome v0.0.0-20240108205627-a1232e345536/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo=
github.com/FortAwesome/Font-Awesome v0.0.0-20240402185447-c0f460dca7f7/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo=
-github.com/google/docsy v0.9.1 h1:+jqges1YCd+yHeuZ1BUvD8V8mEGVtPxULg5j/vaJ984=
-github.com/google/docsy v0.9.1/go.mod h1:saOqKEUOn07Bc0orM/JdIF3VkOanHta9LU5Y53bwN2U=
-github.com/google/docsy v0.10.0 h1:6tMDacPwAyRWNCfvsn/9qGOZDQ8b0aRzjRZvnZPY5dg=
-github.com/google/docsy v0.10.0/go.mod h1:c0nIAqmRTOuJ01F85U/wJPQtc3Zj9N58Kea9bOT2AJc=
-github.com/google/docsy/dependencies v0.6.0/go.mod h1:EDGc2znMbGUw0RW5kWwy2oGgLt0iVXBmoq4UOqstuNE=
+github.com/FortAwesome/Font-Awesome v0.0.0-20241216213156-af620534bfc3/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo=
+github.com/google/docsy v0.12.0 h1:CddZKL39YyJzawr8GTVaakvcUTCJRAAYdz7W0qfZ2P4=
+github.com/google/docsy v0.12.0/go.mod h1:1bioDqA493neyFesaTvQ9reV0V2vYy+xUAnlnz7+miM=
github.com/google/docsy/dependencies v0.7.2 h1:+t5ufoADQAj4XneFphz4A+UU0ICAxmNaRHVWtMYXPSI=
github.com/google/docsy/dependencies v0.7.2/go.mod h1:gihhs5gmgeO+wuoay4FwOzob+jYJVyQbNaQOh788lD4=
github.com/twbs/bootstrap v4.6.2+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0=
github.com/twbs/bootstrap v5.2.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0=
github.com/twbs/bootstrap v5.3.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0=
+github.com/twbs/bootstrap v5.3.6+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0=
diff --git a/layouts/publications/list.html b/layouts/publications/list.html
new file mode 100644
index 00000000..bbac6e67
--- /dev/null
+++ b/layouts/publications/list.html
@@ -0,0 +1,13 @@
+{{ define "main" }}
+ Publications
+
+ {{ range .Pages.ByWeight }}
+
+ {{ .Title }}
+ {{ .Params.authors | append ", " }}
+ {{ .Params.journal }} , {{ .Params.year }}
+ Read more
+
+ {{ end }}
+
+{{ end }}
\ No newline at end of file
From 86ba56590490c86706c82f059b97008733b5089c Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Sun, 24 Aug 2025 13:52:24 -0400
Subject: [PATCH 08/23] Initial implementation of list of all bibliography
entries
Primitive first pass. Provides a chronological list of all
bibliography entires providing titles, authors, date and an
abbreviated start of the abstract (limted to 24 words). In
addition, a link is enclosed that goes to the markdown file
that represents the bibliography entry.
Currently, there is nothing implemented to show the contents of
the md file.
There is no bibliography css implemented to format the list items.
This provides an initial proof of concept. A simple framework that
can be extended and styled to get us where we want to go.
---
layouts/publications/list.html | 37 +++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/layouts/publications/list.html b/layouts/publications/list.html
index bbac6e67..9b620d30 100644
--- a/layouts/publications/list.html
+++ b/layouts/publications/list.html
@@ -1,12 +1,39 @@
{{ define "main" }}
+
Publications
+ {{- $pages := .Pages.ByParam "date" }}
From a2b6188bb25e950061bc3a15dbcbce824451cab1 Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Sun, 24 Aug 2025 14:30:29 -0400
Subject: [PATCH 09/23] Initial implementation of list of all bibliography
entries
Primitive first pass. Provides a chronological list of all
bibliography entires providing titles, authors, date and an
abbreviated start of the abstract (limted to 24 words). In
addition, a link is enclosed that goes to the markdown file
that represents the bibliography entry.
Currently, there is nothing implemented to show the contents of
the md file.
There is no bibliography css implemented to format the list items.
This provides an initial proof of concept. A simple framework that
can be extended and styled to get us where we want to go.
---
content/en/publications/_index.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 content/en/publications/_index.md
diff --git a/content/en/publications/_index.md b/content/en/publications/_index.md
new file mode 100644
index 00000000..19b4d21a
--- /dev/null
+++ b/content/en/publications/_index.md
@@ -0,0 +1,4 @@
+
+# {{- range .Pages }}
+#
+# {{- end }}
\ No newline at end of file
From 7ff6032e4c1ae2bd25a4becb8f24e23af30ba10d Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Thu, 2 Oct 2025 22:43:59 -0400
Subject: [PATCH 10/23] Updates to bibliography page
The bibliography md files are build using the update_bibliography.sh
script. bib-fns.jq provides functions to reformat the Zotero JSON.
bibSplit.pl creates the md file and a data file containing the JSON
for each page. Future work will remove the JSON data files once all the
content is encompassed in the md file.
Added new document type bibliography to generate the list of
bibliography entries. layouts/bibliography/list.html provides this
functionality. It also currently includes some light css to format the
output. The css will eventually be moved into a standalone file within
the Hugo ecosystem.
Removed the original publication type and its associated files in
layouts.
Removed some HugoBlox files. They were left over from an early attempt
to create a bibliography using HugoBlox as a template.
Updated gh-pages.yml, the GHA, to cache the md pages and JSON files.
Rewrote the caching to make it more efficient and easier to follow.
---
.github/workflows/gh-pages.yml | 48 +++---
assets/js/publication.js | 162 --------------------
assets/scss/publications/_publications.scss | 33 ----
config/_default/module.yaml | 4 +-
content/en/history/bibliography/_index.md | 8 +-
content/en/publications/_index.md | 4 -
layouts/bibliography/list.html | 84 ++++++++++
layouts/partials/hooks/body-end.html | 1 -
layouts/publication/single.html | 76 ---------
layouts/publications/list.html | 40 -----
scripts/bib-fns.jq | 37 +++++
scripts/bibSplit.pl | 39 ++++-
scripts/update_bibliography.sh | 14 +-
13 files changed, 189 insertions(+), 361 deletions(-)
delete mode 100644 assets/js/publication.js
delete mode 100644 assets/scss/publications/_publications.scss
delete mode 100644 content/en/publications/_index.md
create mode 100644 layouts/bibliography/list.html
delete mode 100644 layouts/publication/single.html
delete mode 100644 layouts/publications/list.html
mode change 100644 => 100755 scripts/bibSplit.pl
mode change 100755 => 100644 scripts/update_bibliography.sh
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
index 04353aa3..ed5ead6f 100644
--- a/.github/workflows/gh-pages.yml
+++ b/.github/workflows/gh-pages.yml
@@ -43,7 +43,7 @@ defaults:
env:
# ----------------------------------------------------------------------------
# Specify the deployment environment: staging or production
- HUGO_ENVIRONMENT: production
+ HUGO_ENVIRONMENT: staging
HUGO_VERSION: 0.144.2
jobs:
@@ -57,27 +57,25 @@ jobs:
cacheHit: ${{ steps.cache-zotero-bib.outputs.cache-hit }}
runs-on: ubuntu-latest
- concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
steps:
- name: Get Zotero Version Information
id: zoteroVersion
uses: fjogeleit/http-request-action@v1
with:
- url: "https://api.zotero.org/groups/2914042/items?format=versions"
- method: "GET"
+ url: https://api.zotero.org/groups/2914042/items?format=versions
+ method: GET
- name: Cache Zotero Bibliography
- id: cache-zotero-bib
- uses: actions/cache@v4
- env:
- cache-name: cache-zotero_bib
+ id: cache-zotero
+ uses: actions/cache/restore@v4
with:
- path: ~/data
- key: ${{ fromJson(steps.zoteroVersion.outputs.headers).last-modified-version }}
- restore-keys: |
- ${{ fromJson(steps.zoteroVersion.outputs.headers).last-modified-version }}
+ lookup-only: true
+ path: |
+ static/data/bibliography.json
+ static/data/bibItems
+ content/en/history/bibliography
+ key: bib-${{ fromJson(steps.zoteroVersion.outputs.headers).last-modified-version }}
# ----------------------------------------------------------------------------
# Build the website. This job is conditional, we will always run it on a
@@ -94,33 +92,23 @@ jobs:
fetch-depth: 0
- name: Cache Zotero Bibliography
- id: cache-zotero-bib
+ id: cache-bib
uses: actions/cache@v4
- env:
- cache-name: cache-zotero_bib
with:
- path: ~/data
- key: ${{ needs.check.outputs.zoteroVersion }}
- restore-keys: |
- ${{ needs.check.outputs.zoteroVersion }}
+ path: |
+ static/data/bibliography.json
+ static/data/bibItems
+ content/en/history/bibliography
+ key: bib-${{ needs.check.outputs.zoteroVersion }}
- name: Install Bibliography
- env:
- CACHE_HIT: ${{ steps.cache-zotero-bib.outputs.cache-hit }}
+ if: steps.cache-bib.outputs.cache-hit != 'true'
run: |
- if [[ "$CACHE_HIT" == 'true' ]]; then
- echo "Use Cache"
- sudo cp --recursive ~/data ${GITHUB_WORKSPACE}/static
- ls -la ${GITHUB_WORKSPACE}/static/data
- else
echo "Retrieve bibliography"
cd scripts
chmod +x ./update_bibliography.sh
chmod +x ./bibSplit.pl
-
./update_bibliography.sh
- sudo cp --recursive ${GITHUB_WORKSPACE}/static/data ~/data
- fi
# Install Hugo Extended
#
diff --git a/assets/js/publication.js b/assets/js/publication.js
deleted file mode 100644
index 5faff59f..00000000
--- a/assets/js/publication.js
+++ /dev/null
@@ -1,162 +0,0 @@
-/*************************************************
- * Hugo Blox Builder
- * https://github.com/HugoBlox/hugo-blox-builder
- *
- * Hugo Blox Builder Publications
- **************************************************/
-
-// Active publication filters.
-let pubFilters = {};
-
-// Search term.
-let searchRegex;
-
-// Filter values (concatenated).
-let filterValues;
-
-// Publication container.
-let $grid_pubs = $('#container-publications');
-
-// Initialise Isotope publication layout if required.
-if ($grid_pubs.length) {
- $grid_pubs.isotope({
- itemSelector: '.isotope-item',
- percentPosition: true,
- masonry: {
- // Use Bootstrap compatible grid layout.
- columnWidth: '.grid-sizer',
- },
- filter: function () {
- let $this = $(this);
- let searchResults = searchRegex ? $this.text().match(searchRegex) : true;
- let filterResults = filterValues ? $this.is(filterValues) : true;
- return searchResults && filterResults;
- },
- });
-
- // Filter by search term.
- let $quickSearch = $('.filter-search').keyup(
- debounce(function () {
- searchRegex = new RegExp($quickSearch.val(), 'gi');
- $grid_pubs.isotope();
- }),
- );
-
- $('.pub-filters').on('change', function () {
- let $this = $(this);
-
- // Get group key.
- let filterGroup = $this[0].getAttribute('data-filter-group');
-
- // Set filter for group.
- pubFilters[filterGroup] = this.value;
-
- // Combine filters.
- filterValues = concatValues(pubFilters);
-
- // Activate filters.
- $grid_pubs.isotope();
-
- // If filtering by publication type, update the URL hash to enable direct linking to results.
- if (filterGroup === 'pubtype') {
- // Set hash URL to current filter.
- let url = $(this).val();
- if (url.substr(0, 9) === '.pubtype-') {
- window.location.hash = url.substr(9);
- } else {
- window.location.hash = '';
- }
- }
- });
-}
-
-// Debounce input to prevent spamming filter requests.
-function debounce(fn, threshold) {
- let timeout;
- threshold = threshold || 100;
- return function debounced() {
- clearTimeout(timeout);
- let args = arguments;
- let _this = this;
-
- function delayed() {
- fn.apply(_this, args);
- }
-
- timeout = setTimeout(delayed, threshold);
- };
-}
-
-// Flatten object by concatenating values.
-function concatValues(obj) {
- let value = '';
- for (let prop in obj) {
- value += obj[prop];
- }
- return value;
-}
-
-// Filter publications according to hash in URL.
-function filter_publications() {
- // Check for Isotope publication layout.
- if (!$grid_pubs.length) return;
-
- let urlHash = window.location.hash.replace('#', '');
- let filterValue = '*';
-
- // Check if hash is set.
- if (urlHash != '') {
- filterValue = '.pubtype-' + urlHash;
- }
-
- // Set filter.
- let filterGroup = 'pubtype';
- pubFilters[filterGroup] = filterValue;
- filterValues = concatValues(pubFilters);
-
- // Activate filters.
- $grid_pubs.isotope();
-
- // Set selected option.
- $('.pubtype-select').val(filterValue);
-}
-
-document.addEventListener('DOMContentLoaded', function () {
- // Enable publication filter for publication index page.
- if ($('.pub-filters-select')) {
- filter_publications();
- // Useful for changing hash manually (e.g. in development):
- // window.addEventListener('hashchange', filter_publications, false);
- }
-
- // Load citation modal on 'Cite' click.
- $('.js-cite-modal').click(function (e) {
- e.preventDefault();
- let filename = $(this).attr('data-filename');
- let modal = $('#modal');
- modal.find('.modal-body code').load(filename, function (response, status, xhr) {
- if (status == 'error') {
- let msg = 'Error: ';
- $('#modal-error').html(msg + xhr.status + ' ' + xhr.statusText);
- } else {
- $('.js-download-cite').attr('href', filename);
- }
- });
- modal.modal('show');
- });
-
- // Copy citation text on 'Copy' click.
- $('.js-copy-cite').click(function (e) {
- e.preventDefault();
- // Get text to copy.
- let citation = document.querySelector('#modal .modal-body code').innerHTML;
- navigator.clipboard
- .writeText(citation)
- .then(function () {
- console.debug('Citation copied!');
- })
- .catch(function () {
- console.error('Citation copy failed!');
- });
- });
-});
diff --git a/assets/scss/publications/_publications.scss b/assets/scss/publications/_publications.scss
deleted file mode 100644
index 3f232598..00000000
--- a/assets/scss/publications/_publications.scss
+++ /dev/null
@@ -1,33 +0,0 @@
-/*************************************************
- * Publications
- **************************************************/
-
-.pub-banner {
- max-width: 100%;
- height: auto;
- margin-left: auto;
- margin-right: auto;
-}
-
-.pub-row-heading {
- font-weight: bold;
-}
-
-#container-publications {
- display: block;
- position: relative;
- overflow: hidden;
-}
-
-.li-cite-author {
- font-size: 1em;
- color: inherit;
-}
-
-.li-cite-author a {
- color: inherit;
-}
-
-.dark .li-cite-author a {
- color: rgb(248, 248, 242);
-}
diff --git a/config/_default/module.yaml b/config/_default/module.yaml
index b90b4802..d6c27e0b 100644
--- a/config/_default/module.yaml
+++ b/config/_default/module.yaml
@@ -8,6 +8,4 @@
- path: "github.com/google/docsy"
disable: false
- path: "github.com/google/docsy/dependencies"
- disable: false
- - path: github.com/HugoBlox/hugo-blox-builder/modules/blox-plugin-decap-cms
- - path: github.com/HugoBlox/hugo-blox-builder/modules/blox-bootstrap/v5
\ No newline at end of file
+ disable: false
\ No newline at end of file
diff --git a/content/en/history/bibliography/_index.md b/content/en/history/bibliography/_index.md
index 376de97f..9f56fe8a 100644
--- a/content/en/history/bibliography/_index.md
+++ b/content/en/history/bibliography/_index.md
@@ -1,14 +1,14 @@
---
title: Bibliography
+type: bibliography
+cascade:
+ type: bibliography
weight: 5
-type: docs
aliases:
- /bibliography/
---
-## Interlisp Bibliography
+# Interlisp Bibliography
(This bibliography is kept in sync with our [Zotero](https://www.zotero.org/) collection [Library](https://www.zotero.org/groups/2914042/interlisp/library).
-
-{{< bibTable >}}
diff --git a/content/en/publications/_index.md b/content/en/publications/_index.md
deleted file mode 100644
index 19b4d21a..00000000
--- a/content/en/publications/_index.md
+++ /dev/null
@@ -1,4 +0,0 @@
-
-# {{- range .Pages }}
-#
-# {{- end }}
\ No newline at end of file
diff --git a/layouts/bibliography/list.html b/layouts/bibliography/list.html
new file mode 100644
index 00000000..8d2bfed5
--- /dev/null
+++ b/layouts/bibliography/list.html
@@ -0,0 +1,84 @@
+{{ define "main" }}
+
+
+
+
+ {{ .Content }}
+
+
+
+
+ {{ $pages := .RegularPages }}
+
+ {{- warnf "Pages: $s" (len $pages) -}}
+
+ {{ if not (gt (len $pages) 0) }}
+ No publications found.
+ {{ end }}
+
+ {{- /* Sort by date descending, then title ascending */ -}}
+ {{- $pages = sort $pages "Date" "desc" -}}
+ {{- $pages = sort $pages "Title" "asc" -}}
+
+ {{- /* Render the list of publications */ -}}
+
+
+{{ end }}
\ No newline at end of file
diff --git a/layouts/partials/hooks/body-end.html b/layouts/partials/hooks/body-end.html
index 967e03be..2454aa2d 100644
--- a/layouts/partials/hooks/body-end.html
+++ b/layouts/partials/hooks/body-end.html
@@ -1,6 +1,5 @@
-
{{range .Site.Params.custom_css -}}
{{- end}}
diff --git a/layouts/publication/single.html b/layouts/publication/single.html
deleted file mode 100644
index ad8d50d1..00000000
--- a/layouts/publication/single.html
+++ /dev/null
@@ -1,76 +0,0 @@
-{{- define "main" -}}
-
-{{ warnf "Debug message: enter publication single template for %s" .RelPermalink }}
-
-{{ $page := . }}
-{{ $site := .Site }}
-
-{{ partial "head.html" . }}
-
-{{/* Set the page title */}}
-{{ $title := .Title | default ("publication") }}
-
-{{/* Set the page description */}}
-{{ $description := .Params.description | default ("publication_description") }}
-
-{{ $pub_type_csl := "" }}
-{{ $pub_type_display := "" }}
-{{ if .Params.publication_types }}
- {{ if reflect.IsSlice .Params.publication_types }}
- {{ $pub_type_csl = index .Params.publication_types 0 }}
- {{ $pub_type_display = printf "pub_%s" (strings.Replace $pub_type_csl "-" "_") | default (strings.Title $pub_type_csl) }}
- {{ end }}
-{{ end }}
-
-
-
-
-
-
- {{ if .Params.abstract }}
-
{{ "abstract" }}
-
{{ .Params.abstract | markdownify }}
- {{ end }}
-
- {{/* If the type is Uncategorized, hide the type. */}}
- {{ if $pub_type_display }}
-
-
-
-
-
{{ "publication_type" }}
-
-
-
-
-
-
- {{ end }}
-
- {{ if .Params.publication }}
-
-
-
-
-
{{ "publication" }}
-
{{ .Params.publication | markdownify }}
-
-
-
-
-
- {{ end }}
-
-
-
-
{{ .Content }}
-
- {{ partial "page_footer" . }}
-
-
-
-{{- end -}}
diff --git a/layouts/publications/list.html b/layouts/publications/list.html
deleted file mode 100644
index 9b620d30..00000000
--- a/layouts/publications/list.html
+++ /dev/null
@@ -1,40 +0,0 @@
-{{ define "main" }}
-
- Publications
- {{- $pages := .Pages.ByParam "date" }}
-
-{{ end }}
\ No newline at end of file
diff --git a/scripts/bib-fns.jq b/scripts/bib-fns.jq
index 668a0a3a..7149ce56 100644
--- a/scripts/bib-fns.jq
+++ b/scripts/bib-fns.jq
@@ -15,6 +15,43 @@ def moveURL_to_url:
def raise_issued_date_parts:
if nonBlankKey("issued") and (.issued | nonBlankKey("date-parts")) then setpath(["issuedDateParts"]; .issued."date-parts"[0]) else . end;
+def pad2: tostring | if length==1 then "0"+. else . end;
+
+def issued_iso_string:
+ if nonBlankKey("issued") and (.issued | nonBlankKey("date-parts")) then
+ setpath(["isoDateString"];
+ (.issued["date-parts"][0]) as $p | ($p[0]|tostring) + "-" + (($p[1]? // 1)|pad2) + "-" + (($p[2]? // 1)|pad2))
+ else
+ .
+ end;
+
+# Build "Family, Given; Family2, Given2" string from .author array.
+# Falls back to other common shapes (name / firstName+lastName). Skips empty parts.
+def author_string:
+ ( .author // [] ) # if no authors → empty array
+ | map(
+ if (has("family") and .family != null and (.family|tostring|length)>0) then
+ .family
+ + ( if (has("given") and .given != null and (.given|tostring|length)>0)
+ then ", " + (.given|tostring)
+ else "" end )
+ elif (has("lastName") and .lastName != null) then
+ .lastName
+ + ( if (has("firstName") and .firstName != null and (.firstName|tostring|length)>0)
+ then ", " + (.firstName|tostring)
+ else "" end )
+ elif (has("name") and .name != null) then
+ .name
+ else
+ empty
+ end
+ )
+ | join("; ");
+
+# If you want the field added into each item:
+def add_author_string:
+ . + { authorsFormatted: (author_string) };
+
def make_DOI_to_url($doi):
if ($doi | startswith("https:")) then $doi else "https://doi.org/" + ($doi | ltrimstr("/")) end ;
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
old mode 100644
new mode 100755
index b84819c6..f72a1a8a
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -16,16 +16,47 @@ BEGIN
print $handle $item;
close $handle || die "$0: close of file $itemjson failed: $!";
- /"title"\:("(?:[^"\\]++|\\.)*+")/ || print "Cannot find title for key \"$key\" in line: $_\n";
- my $itemTitle = $1;
+ my $itemTitle = '""';
+ if(/"title"\:("(?:[^"\\]++|\\.)*+")/) {
+ $itemTitle = $1;
+ } else {
+ print "Cannot find title for key \"$key\" in line: $_\n";
+ }
+
+ my $itemAbstract = '""';
+ if(/"abstract"\:("(?:[^"\\]++|\\.)*+")/) {
+ $itemAbstract = $1;
+ } else {
+ print "Cannot find abstract for key \"$key\" in line: $_\n";
+ }
+
+ my $itemDate = '""';
+ if(/"isoDateString"\:("(?:[^"\\]++|\\.)*+")/) {
+ $itemDate = $1;
+ } else {
+ print "Cannot find isoDateString for key \"$key\" in line: $_\n";
+ }
+
+ my $itemAuthors = '""';
+ if(/"authorsFormatted"\:("(?:[^"\\]++|\\.)*+")/) {
+ $itemAuthors = $1;
+ } else {
+ print "Cannot find authors for key \"$key\" in line: $_\n";
+ }
+
$handle = undef;
my $itemmd = "$bibDir/$key.md";
open($handle, ">", $itemmd) || die "$0: cannot open $itemmd in write-open mode: $!";
print $handle <}}
diff --git a/scripts/update_bibliography.sh b/scripts/update_bibliography.sh
old mode 100755
new mode 100644
index 327ff1c0..437b4aad
--- a/scripts/update_bibliography.sh
+++ b/scripts/update_bibliography.sh
@@ -3,7 +3,7 @@
set -e
rawItemsFile=false
-debugFiles=true
+debugFiles=false
tagFiles=false
typeFiles=true
curlFiles=false
@@ -264,7 +264,9 @@ if $debugFiles ; then
fi
finalCount=$(jq '. | length' <<< "$items")
-items=$(jq 'include "./bib-fns";map(raise_issued_date_parts)' <<< "$items")
+items=$(jq 'include "./bib-fns";map(issued_iso_string)' <<< "$items")
+
+items=$(jq 'include "./bib-fns";map(add_author_string)' <<< "$items")
# if $removeChildrenFromFinalFile; then
# # Remove .children arrays, if any. Save space.
# items=$(jq 'map(del(.children))' <<< "$items")
@@ -295,10 +297,14 @@ if $debugFiles ; then
fi
showInfo 1 "Generating individual Bibliography entries' .md files"
-BIBLIOGRAPHY_DIR="$(dirname "$0")/../content/en/history/bibliography"
+BIBLIOGRAPHY_DIR="./../content/en/history/bibliography"
export BIBLIOGRAPHY_DIR
-BIBITEMS_DIR="$(dirname "$0")/../static/data/bibItems"
+BIBITEMS_DIR="./../static/data/bibItems"
export BIBITEMS_DIR
+
+# Ensure target directories exist
+mkdir -p "$BIBLIOGRAPHY_DIR" "$BIBITEMS_DIR"
+
./bibSplit.pl bibliography-items-by-line.json
# Cleanup (uncomment once working)
# rm bibliography-items-by-line.json
From 8dba241e882a8d2da060cb3852f86d1db23d04c4 Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Wed, 8 Oct 2025 21:31:15 -0400
Subject: [PATCH 11/23] Update bibliography entry to link to Zotero
The Read Me link now points to the Zotero entry for
each item.
---
layouts/bibliography/list.html | 7 ++++++-
scripts/bibSplit.pl | 4 ++++
scripts/update_bibliography.sh | 0
3 files changed, 10 insertions(+), 1 deletion(-)
mode change 100644 => 100755 scripts/update_bibliography.sh
diff --git a/layouts/bibliography/list.html b/layouts/bibliography/list.html
index 8d2bfed5..6a11887d 100644
--- a/layouts/bibliography/list.html
+++ b/layouts/bibliography/list.html
@@ -76,7 +76,12 @@
{{ $authors }}
{{- end -}}
{{- end -}}
- Read more
+
+ {{- $zotero_url := .Params.zotero_url -}}
+
+ {{- if $zotero_url -}}
+ Read More
+ {{- end -}}
{{ end }}
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index f72a1a8a..29b29ae9 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -57,8 +57,12 @@ BEGIN
abstract_short:
tags:
url_source:
+zotero_url: "https://www.zotero.org/groups/2914042/items/$key"
---
+
+[Read More]({{< param "zotero_url" >}})
+
{{< bibItem key="$key" >}}
ENDITEM
close $handle || die "$0: close of file $itemmd failed: $!";
diff --git a/scripts/update_bibliography.sh b/scripts/update_bibliography.sh
old mode 100644
new mode 100755
From c8b317feb7c588b8bb90b1f8b52af17945fb217e Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Wed, 8 Oct 2025 21:44:58 -0400
Subject: [PATCH 12/23] Add missing edits.
---
scripts/bibSplit.pl | 3 ---
1 file changed, 3 deletions(-)
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index 29b29ae9..e28e0125 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -60,9 +60,6 @@ BEGIN
zotero_url: "https://www.zotero.org/groups/2914042/items/$key"
---
-
-[Read More]({{< param "zotero_url" >}})
-
{{< bibItem key="$key" >}}
ENDITEM
close $handle || die "$0: close of file $itemmd failed: $!";
From ca4ac24bad3489aacdc570744bb4915034070392 Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Wed, 8 Oct 2025 23:04:19 -0400
Subject: [PATCH 13/23] Update Zotero link wording and open in new tab
---
layouts/bibliography/list.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/layouts/bibliography/list.html b/layouts/bibliography/list.html
index 6a11887d..07aa4e15 100644
--- a/layouts/bibliography/list.html
+++ b/layouts/bibliography/list.html
@@ -76,11 +76,11 @@
{{ $authors }}
{{- end -}}
{{- end -}}
-
+
{{- $zotero_url := .Params.zotero_url -}}
{{- if $zotero_url -}}
- Read More
+ View on Zotero
{{- end -}}
From aee5b11dc96ef4eee29719fa5403abd95541b59f Mon Sep 17 00:00:00 2001
From: Matt Heffron
Date: Wed, 8 Oct 2025 20:55:53 -0700
Subject: [PATCH 14/23] Fixed a few Hugo syntax errors. Changed the de-html &
re-html encoding to remove unnecessary encoding of html entities. bibSplit.pl
errors go to STDERR update_bibliography.sh redirects those errors to
bibSplit.err file.
I cannot find Hugo documentation showing why _ in truncated abstract renders as ellipsis.
---
layouts/bibliography/list.html | 36 +++++++++++++++++-----------------
scripts/bibSplit.pl | 12 ++++++------
scripts/update_bibliography.sh | 2 +-
3 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/layouts/bibliography/list.html b/layouts/bibliography/list.html
index 07aa4e15..06996877 100644
--- a/layouts/bibliography/list.html
+++ b/layouts/bibliography/list.html
@@ -25,7 +25,7 @@
{{ $pages := .RegularPages }}
- {{- warnf "Pages: $s" (len $pages) -}}
+ {{- warnf "Pages: %v" (len $pages) -}}
{{ if not (gt (len $pages) 0) }}
No publications found.
@@ -42,33 +42,33 @@
{{- $rawTitle := or .Params.title .Title -}}
{{- $rendered := replaceRE "^(.*)
$" "$1" $rawTitle -}}
- {{- $rendered = $rawTitle | markdownify -}}
- {{ $rendered }}
+ {{- $rendered = $rawTitle | plainify | htmlEscape -}}
+ {{- $rendered | safeHTML -}}
- {{- /* warnf "Parameters $s " .Params */ -}}
+ {{- /* warnf "Parameters %v " .Params */ -}}
- {{/* Safe date: use front matter date only if non-empty & matches basic pattern */}}
- {{ $d := .Date }}
- {{ with .Params.date }}
- {{ $datestr := trim . " " }}
- {{ if and (ne $datestr "") (findRE `^\d{4}-\d{2}-\d{2}` $datestr) }}
- {{ $d = time $datestr }}
- {{ end }}
- {{ end }}
+ {{- /* Safe date: use front matter date only if non-empty & matches basic pattern */ -}}
+ {{- $d := .Date -}}
+ {{- with .Params.date -}}
+ {{- $datestr := trim . " " -}}
+ {{- if and (ne $datestr "") (findRE `^\d{4}-\d{2}-\d{2}` $datestr) -}}
+ {{- $d = time $datestr -}}
+ {{- end -}}
+ {{- end }}
{{ $d.Format "2006-01-02" }}
- {{ with .Params.abstract }}
- {{- $plain := . | markdownify | plainify | replaceRE `\s+` " " -}}
+ {{ with .Params.abstract -}}
+ {{- $plain := . | plainify | htmlEscape | replaceRE `\s+` " " -}}
{{- $words := split $plain " " -}}
{{- $previewWords := cond (gt (len $words) 24) (first 24 $words) $words -}}
{{- $preview := delimit $previewWords " " -}}
- {{ $preview }}{{ if gt (len $words) 24 }}…{{ end }}
+ {{ $preview | safeHTML }}{{ if gt (len $words) 24 }}…{{ end }}
- {{ end }}
+ {{- end -}}
{{- $authors := .Params.authors -}}
- {{- /* warnf "authors: $s" $authors */ -}}
+ {{- /* warnf "authors: %v" $authors */ -}}
{{- if $authors -}}
{{- if reflect.IsSlice $authors -}}
{{ delimit $authors ", " " and " }}
@@ -79,7 +79,7 @@
{{- $zotero_url := .Params.zotero_url -}}
- {{- if $zotero_url -}}
+ {{- if $zotero_url }}
View on Zotero
{{- end -}}
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index e28e0125..d74291e0 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -5,9 +5,9 @@ BEGIN
$bibItemsDir = $ENV{'BIBITEMS_DIR'};
}
my $item = $_;
-/"key"\:"([A-Za-z0-9]{8})"/ || print "Cannot find key in line: $_\n";
+/"key"\:"([A-Za-z0-9]{8})"/ || print STDERR "Cannot find key in line: $_\n";
my $key = $1;
-/"target"\:"([A-Za-z0-9]{8})"/ || print "Cannot find target for key \"$key\" in line: $_\n";
+/"target"\:"([A-Za-z0-9]{8})"/ || print STDERR "Cannot find target for key \"$key\" in line: $_\n";
my $target = $1;
if ($key eq $target) { # only top level entries
my $handle = undef;
@@ -20,28 +20,28 @@ BEGIN
if(/"title"\:("(?:[^"\\]++|\\.)*+")/) {
$itemTitle = $1;
} else {
- print "Cannot find title for key \"$key\" in line: $_\n";
+ print STDERR "Cannot find title for key \"$key\" in line: $_\n";
}
my $itemAbstract = '""';
if(/"abstract"\:("(?:[^"\\]++|\\.)*+")/) {
$itemAbstract = $1;
} else {
- print "Cannot find abstract for key \"$key\" in line: $_\n";
+ print STDERR "Cannot find abstract for key \"$key\" in line: $_\n";
}
my $itemDate = '""';
if(/"isoDateString"\:("(?:[^"\\]++|\\.)*+")/) {
$itemDate = $1;
} else {
- print "Cannot find isoDateString for key \"$key\" in line: $_\n";
+ print STDERR "Cannot find isoDateString for key \"$key\" in line: $_\n";
}
my $itemAuthors = '""';
if(/"authorsFormatted"\:("(?:[^"\\]++|\\.)*+")/) {
$itemAuthors = $1;
} else {
- print "Cannot find authors for key \"$key\" in line: $_\n";
+ print STDERR "Cannot find authors for key \"$key\" in line: $_\n";
}
$handle = undef;
diff --git a/scripts/update_bibliography.sh b/scripts/update_bibliography.sh
index 437b4aad..8ff3da57 100755
--- a/scripts/update_bibliography.sh
+++ b/scripts/update_bibliography.sh
@@ -305,7 +305,7 @@ export BIBITEMS_DIR
# Ensure target directories exist
mkdir -p "$BIBLIOGRAPHY_DIR" "$BIBITEMS_DIR"
-./bibSplit.pl bibliography-items-by-line.json
+./bibSplit.pl bibliography-items-by-line.json 2>bibSplit.err
# Cleanup (uncomment once working)
# rm bibliography-items-by-line.json
From c45050d0fd39e8d3053c7b53864c32305ce766a9 Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Wed, 15 Oct 2025 08:00:29 -0400
Subject: [PATCH 15/23] Updates to author tags
Authors are now stored as a list of strings in the YAML, one author per
line in the list.
Previously all the authors were consolidated into a single string.
---
scripts/bib-fns.jq | 17 +++++++++++------
scripts/bibSplit.pl | 21 ++++++++++++++++++---
2 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/scripts/bib-fns.jq b/scripts/bib-fns.jq
index 7149ce56..6de5ce07 100644
--- a/scripts/bib-fns.jq
+++ b/scripts/bib-fns.jq
@@ -1,5 +1,10 @@
# Module of JQ functions for manipulating JSON returned from Zotero API
+def dbg($label; $value):
+ . as $in
+ | (($label + ": " + ($value | tojson)) | debug) # prints to stderr
+ | $in; # return original value
+
def nonBlankKey($keyName):
has($keyName) and (.[$keyName] | tostring | length >= 1);
@@ -25,10 +30,11 @@ def issued_iso_string:
.
end;
-# Build "Family, Given; Family2, Given2" string from .author array.
+# Build ["Family, Given", "Family2, Given2", ...] string array from .author array.
# Falls back to other common shapes (name / firstName+lastName). Skips empty parts.
-def author_string:
- ( .author // [] ) # if no authors → empty array
+def author_string_list:
+ ( .author // [] )
+ | dbg("author_string_list.count"; length)
| map(
if (has("family") and .family != null and (.family|tostring|length)>0) then
.family
@@ -45,12 +51,11 @@ def author_string:
else
empty
end
- )
- | join("; ");
+ );
# If you want the field added into each item:
def add_author_string:
- . + { authorsFormatted: (author_string) };
+ . + { authorsFormatted: (author_string_list) };
def make_DOI_to_url($doi):
if ($doi | startswith("https:")) then $doi else "https://doi.org/" + ($doi | ltrimstr("/")) end ;
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index d74291e0..1e805ea1 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -37,10 +37,25 @@ BEGIN
print STDERR "Cannot find isoDateString for key \"$key\" in line: $_\n";
}
- my $itemAuthors = '""';
- if(/"authorsFormatted"\:("(?:[^"\\]++|\\.)*+")/) {
- $itemAuthors = $1;
+ my $itemAuthors = '';
+ if(/"authorsFormatted"\:\s*\[(.*?)\]/) {
+ my $authors_str = $1;
+ my @authors;
+ while ($authors_str =~ /"(.*?)"/g) {
+ push @authors, $1;
+ }
+ if (@authors) {
+ $itemAuthors = "\n";
+ foreach my $author (@authors) {
+ $itemAuthors .= " - \"$author\"\n";
+ }
+ $itemAuthors =~ s/\n$//; # Remove trailing newline
+ } else {
+ $itemAuthors = '""';
+ print STDERR "Cannot parse authors for key \"$key\" in line: $_\n";
+ }
} else {
+ $itemAuthors = '""';
print STDERR "Cannot find authors for key \"$key\" in line: $_\n";
}
From c9ccc82a03e0253248f4c40f26e33532be410b51 Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Mon, 20 Oct 2025 08:00:45 -0400
Subject: [PATCH 16/23] Start of building out individual bibliography pages
Create baseof.html -
framework for bibliography screen single.html - layout of individual
entry
Updated list.html - with baseof, s added at beginning of file are no
longer needed.
Updated bibSplit.pl specify each page as a bibliography page.
---
layouts/bibliography/baseof.html | 37 ++++++++++++++++++++++++++++++
layouts/bibliography/list.html | 3 ---
layouts/bibliography/single.html | 39 ++++++++++++++++++++++++++++++++
scripts/bibSplit.pl | 2 +-
4 files changed, 77 insertions(+), 4 deletions(-)
create mode 100644 layouts/bibliography/baseof.html
create mode 100644 layouts/bibliography/single.html
diff --git a/layouts/bibliography/baseof.html b/layouts/bibliography/baseof.html
new file mode 100644
index 00000000..5f5bec26
--- /dev/null
+++ b/layouts/bibliography/baseof.html
@@ -0,0 +1,37 @@
+
+
+
+ {{ partial "head.html" . }}
+
+
+
+ {{ partial "navbar.html" . }}
+
+
+
+
+
+
+
+ {{ partial "version-banner.html" . }}
+ {{ if not (.Param "ui.breadcrumb_disable") -}}
+ {{ partial "breadcrumb.html" . -}}
+ {{ end -}}
+ {{ block "main" . }}{{ end }}
+
+
+
+ {{ partial "footer.html" . }}
+
+ {{ partial "scripts.html" . }}
+
+
\ No newline at end of file
diff --git a/layouts/bibliography/list.html b/layouts/bibliography/list.html
index 06996877..b35a7eb1 100644
--- a/layouts/bibliography/list.html
+++ b/layouts/bibliography/list.html
@@ -1,7 +1,4 @@
{{ define "main" }}
-
-
-
{{ .Content }}
diff --git a/layouts/bibliography/single.html b/layouts/bibliography/single.html
new file mode 100644
index 00000000..54a13eb5
--- /dev/null
+++ b/layouts/bibliography/single.html
@@ -0,0 +1,39 @@
+{{ define "main" }}
+
+ {{ .Title }}
+
+
+{{- if .Params.authors -}}
+ {{- if reflect.IsSlice .Params.authors -}}
+ {{ delimit .Params.authors ", " " and " }}
+ {{- else -}}
+ {{ .Params.authors }}
+ {{- end -}}
+{{- end -}}
+
+
+
+ {{- $d := .Date -}}
+ {{- with .Params.date }}{{ $d = time . }}{{ end }}
+ {{ $d.Format "2006-01-02" }}
+
+
+ Cite --- URL
+
+
+ Abstract
+
+ {{ with .Params.abstract }}
+ {{ . | markdownify }}
+ {{ else }}
+ No abstract available.
+ {{ end }}
+
+
+
+ Publisher: {{ .Params.publisher }}
+
+ {{ .Content }}
+
+
+{{ end }}
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index 1e805ea1..bd93dd4d 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -66,6 +66,7 @@ BEGIN
---
title: $itemTitle
date: $itemDate
+type: bibliography
authors: $itemAuthors
publication:
abstract: $itemAbstract
@@ -75,7 +76,6 @@ BEGIN
zotero_url: "https://www.zotero.org/groups/2914042/items/$key"
---
-{{< bibItem key="$key" >}}
ENDITEM
close $handle || die "$0: close of file $itemmd failed: $!";
From 49411f71e94b0a66e1222510dd5236259d38dabb Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Wed, 22 Oct 2025 08:58:21 -0400
Subject: [PATCH 17/23] Continued work on creating individual entries.
Build out parsing of json to get needed items
and putting the items into the generated pages.
---
layouts/bibliography/single.html | 99 +++++++++++++++++++++++++++-
scripts/bibSplit.pl | 107 ++++++++++++++++++++-----------
2 files changed, 166 insertions(+), 40 deletions(-)
diff --git a/layouts/bibliography/single.html b/layouts/bibliography/single.html
index 54a13eb5..097e54ac 100644
--- a/layouts/bibliography/single.html
+++ b/layouts/bibliography/single.html
@@ -31,7 +31,104 @@ {{ .Title }}
- Publisher: {{ .Params.publisher }}
+
+ {{ if eq .Params.item_type "book" }}
+ {{ with .Params.publisher }}
+
Publisher: {{ . }}
+ {{ end }}
+ {{ with .Params.place }}
+ {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "paper-conference" }}
+ {{ with .Params.proceedings_title }}
+ Proceedings: {{ . }}
+ {{ end }}
+ {{ with .Params.publisher }}
+ Journal: {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "article" }}
+ {{ with .Params.publisher }}
+ Publisher: {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "article-journal" }}
+ {{ with .Params.publication_title }}
+ Journal: {{ . }}
+ {{ end }}
+ {{ with .Params.volume }}
+ Volume: {{ . }}
+ {{ end }}
+ {{ with .Params.issue }}
+ Issue: {{ . }}
+ {{ end }}
+ {{ with .Params.pages }}
+ Pages: {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "report" }}
+ {{ with .Params.publication_title }}
+ Publisher: {{ . }}
+ {{ end }}
+ {{ with .Params.reportType }}
+ Report Type: {{ . }}
+ {{ end }}
+ {{ with .Params.reportNumber }}
+ Report Number: {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "thesis" }}
+ {{ with .Params.university }}
+ University: {{ . }}
+ {{ end }}
+ {{ with .Params.place }}
+ Place: {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "patent" }}
+ {{ with .Params.assignee }}
+ Assignee: {{ . }}
+ {{ end }}
+ {{ with .Params.application_number }}
+ Application Number: {{ . }}
+ {{ end }}
+ {{ with .Params.filing_date }}
+ Filing Date: {{ . }}
+ {{ end }}
+ {{ with .Params.issuing_authority }}
+ Issuing Authority: {{ . }}
+ {{ end }}
+ {{ with .Params.patent_number }}
+ Patent Number: {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "post-weblog" }}
+ {{ with .Params.blog_title }}
+ Blog Title: {{ . }}
+ {{ end }}
+ {{ end }}
+ {{ if eq .Params.item_type "article-magazine" }}
+ {{ with .Params.publication_title }}
+ Magazine: {{ . }}
+ {{ end }}
+ {{ with .Params.volume }}
+ Volume: {{ . }}
+ {{ end }}
+ {{ with .Params.issue }}
+ Issue: {{ . }}
+ {{ end }}
+ {{ with .Params.pages }}
+ Pages: {{ . }}
+ {{ end }}
+ {{ end }}
+
+
+ {{- if .Params.zotero_url }}
+ View on Zotero
+ {{- end -}}
+
+
{{ .Content }}
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index bd93dd4d..bae3206f 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -1,10 +1,14 @@
#! /usr/bin/perl -n
+use JSON::PP qw(decode_json encode_json);
+use Encode qw(encode);
+
BEGIN
{
$bibDir = $ENV{'BIBLIOGRAPHY_DIR'};
$bibItemsDir = $ENV{'BIBITEMS_DIR'};
}
my $item = $_;
+
/"key"\:"([A-Za-z0-9]{8})"/ || print STDERR "Cannot find key in line: $_\n";
my $key = $1;
/"target"\:"([A-Za-z0-9]{8})"/ || print STDERR "Cannot find target for key \"$key\" in line: $_\n";
@@ -15,50 +19,74 @@ BEGIN
open($handle, ">", $itemjson) || die "$0: cannot open $itemjson in write-open mode: $!";
print $handle $item;
close $handle || die "$0: close of file $itemjson failed: $!";
-
- my $itemTitle = '""';
- if(/"title"\:("(?:[^"\\]++|\\.)*+")/) {
- $itemTitle = $1;
- } else {
- print STDERR "Cannot find title for key \"$key\" in line: $_\n";
- }
- my $itemAbstract = '""';
- if(/"abstract"\:("(?:[^"\\]++|\\.)*+")/) {
- $itemAbstract = $1;
- } else {
- print STDERR "Cannot find abstract for key \"$key\" in line: $_\n";
- }
- my $itemDate = '""';
- if(/"isoDateString"\:("(?:[^"\\]++|\\.)*+")/) {
- $itemDate = $1;
- } else {
- print STDERR "Cannot find isoDateString for key \"$key\" in line: $_\n";
- }
+my $obj = eval { decode_json($item) } or do { warn "Bad JSON for $key\n"; next; };
+delete $obj->{children};
+
+my $type = $obj->{type} // '';
+
+my $itemTitle = '""';
+if (defined $obj->{title} && $obj->{title} ne '') {
+ $itemTitle = encode('ASCII', encode_json($obj->{title})); # => "The \"editor\" ..."
+}
+my $itemAbstract = '""';
+if (defined $obj->{abstract} && $obj->{abstract} ne '') {
+ $itemAbstract = encode('ASCII', encode_json($obj->{abstract})); # => "The \"editor\" ..."
+}
+my $itemDate = defined $obj->{isoDateString} ? $obj->{isoDateString} : '';
my $itemAuthors = '';
- if(/"authorsFormatted"\:\s*\[(.*?)\]/) {
- my $authors_str = $1;
- my @authors;
- while ($authors_str =~ /"(.*?)"/g) {
- push @authors, $1;
- }
- if (@authors) {
- $itemAuthors = "\n";
- foreach my $author (@authors) {
- $itemAuthors .= " - \"$author\"\n";
- }
- $itemAuthors =~ s/\n$//; # Remove trailing newline
- } else {
- $itemAuthors = '""';
- print STDERR "Cannot parse authors for key \"$key\" in line: $_\n";
+ if (ref($obj->{authorsFormatted}) eq 'ARRAY' && @{$obj->{authorsFormatted}}) {
+ $itemAuthors = "\n";
+ for my $a (@{$obj->{authorsFormatted}}) {
+ my $quoted = encode_json($a // '');
+ $itemAuthors .= " - $quoted\n";
}
- } else {
- $itemAuthors = '""';
- print STDERR "Cannot find authors for key \"$key\" in line: $_\n";
+ $itemAuthors =~ s/\n$//; # strip trailing newline
}
+# optional fields - ones used vary by value of type
+ my $applicationNumber = defined $obj->{applicationNumber} ? qq{"$obj->{applicationNumber}"} : '""';
+ my $assignee = defined $obj->{assignee} ? qq{"$obj->{assignees}"} : '""';
+ my $blogTitle = defined $obj->{blogTitle} ? qq{"$obj->{blogTitle}"} : '""';
+ my $conferenceName = defined $obj->{conferenceName} ? qq{"$obj->{conferenceName}"} : '""';
+ my $filingDate = defined $obj->{filingDate} ? qq{"$obj->{filingDate}"} : '""';
+ my $issue = defined $obj->{issue} ? qq{"$obj->{issue}"} : '""';
+ my $issueDate = defined $obj->{issueDate} ? qq{"$obj->{issueDate}"} : '""';
+ my $issuingAuthority = defined $obj->{issuingAuthority} ? qq{"$obj->{issuingAuthority}"} : '""';
+ my $pages = defined $obj->{pages} ? qq{"$obj->{pages}"} : '""';
+ my $patentNumber = defined $obj->{patentNumber} ? qq{"$obj->{patentNumber}"} : '""';
+ my $place = defined $obj->{place} ? qq{"$obj->{place}"} : '""';
+ my $proceedingsTitle = defined $obj->{proceedingsTitle} ? qq{"$obj->{proceedingsTitle}"} : '""';
+ my $publisher = defined $obj->{publisher} ? qq{"$obj->{publisher}"} : '""';
+ my $publicationTitle = defined $obj->{publicationTitle} ? qq{"$obj->{publicationTitle}"} : '""';
+ my $reportNumber = defined $obj->{reportNumber} ? qq{"$obj->{reportNumber}"} : '""';
+ my $reportType = defined $obj->{reportType} ? qq{"$obj->{reportType}"} : '""';
+ my $university = defined $obj->{university} ? qq{"$obj->{university}"} : '""';
+ my $volume = defined $obj->{volume} ? qq{"$obj->{volume}"} : '""';
+
+
+
+my $extraFields = '';
+if ($type eq 'paper-conference') {
+ $extraFields = "conference_name: $conferenceName\nplace: $place\nproceedings_title: $proceedingsTitle\npublisher: $publisher\npages: $pages\n";
+} elsif ($type eq 'article-journal' || $itemTypeVal eq 'article_magazine') {
+ $extraFields = "publication_title: $publicationTitle\nvolume: $volume\nissue: $issue\npages: $pages\n";
+} elsif ($type eq 'article') {
+ $extraFields = "publisher: $publisher\n";
+} elsif ($type eq 'book') {
+ $extraFields = "publisher: $publisher\nplace: $place\n";
+} elsif ($type eq 'report') {
+ $extraFields = "publisher: $publisher\nreport_number: $reportNumber\nreport_type: $reportType\n";
+} elsif ($type eq 'thesis') {
+ $extraFields = "university: $university\nplace: $place\n";
+} elsif ($type eq 'blogPost') {
+ $extraFields = "blog_title: $blogTitle\n";
+} elsif ($type eq 'patent') {
+ $extraFields = "assignee: $assignee\napplication_number: $applicationNumber\nfiling_date: $filingDate\nissuing_authority: $issuingAuthority\npatent_number: $patentNumber\n";
+}
+
$handle = undef;
my $itemmd = "$bibDir/$key.md";
open($handle, ">", $itemmd) || die "$0: cannot open $itemmd in write-open mode: $!";
@@ -67,10 +95,11 @@ BEGIN
title: $itemTitle
date: $itemDate
type: bibliography
+item_type: $type
authors: $itemAuthors
-publication:
abstract: $itemAbstract
-abstract_short:
+
+$extraFields
tags:
url_source:
zotero_url: "https://www.zotero.org/groups/2914042/items/$key"
From fb57d07441142a85dfe8d2afc785746f74ed1c2f Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Thu, 23 Oct 2025 08:01:50 -0400
Subject: [PATCH 18/23] Finish individual bibliography entry creation
Individual bibliography entries are created for
all document types. Customized the entries shown
based on Zotero entries. Added url, left placeholder
for citation.
Updated list of bibliography entries to link to
individual entries.
---
layouts/bibliography/list.html | 14 +---
layouts/bibliography/single.html | 60 +++++++++++++-
scripts/bibSplit.pl | 137 +++++++++++++++++++++----------
3 files changed, 155 insertions(+), 56 deletions(-)
diff --git a/layouts/bibliography/list.html b/layouts/bibliography/list.html
index b35a7eb1..e24b3493 100644
--- a/layouts/bibliography/list.html
+++ b/layouts/bibliography/list.html
@@ -2,7 +2,6 @@
{{ .Content }}
-
+ {{- $previewWordLimit := 24 -}}
{{ $pages := .RegularPages }}
{{- warnf "Pages: %v" (len $pages) -}}
@@ -38,11 +39,41 @@
{{- $rawTitle := or .Params.title .Title -}}
{{- $rendered := replaceRE "^(.*)
$" "$1" $rawTitle -}}
- {{- $rendered = $rendered | plainify | htmlEscape -}}
+ {{- /* The plainify corrupts values that look like HTML but aren't: "Special files on ARs>" */ -}}
+ {{- /* $rendered = $rendered | plainify | htmlEscape */ -}}
+ {{- $rendered = $rendered | htmlEscape -}}
{{- $rendered | safeHTML -}}
{{- /* warnf "Parameters %v " .Params */ -}}
+ {{- $authors := .Params.authors -}}
+ {{- $editors := .Params.editors -}}
+ {{- $isPatent := eq .Params.item_type "patent" -}}
+ {{- /* warnf "authors: %v" $authors */ -}}
+ {{- if or $authors $editors -}}
+ {{- if $authors -}}
+ {{- if reflect.IsSlice $authors -}}
+ {{- if $isPatent }}
+ Inventors:
+ {{ end }}
+ {{ delimit $authors "; " "; and " }}
+ {{- else -}}
+ {{- if $isPatent }}
+ Inventor:
+ {{ end }}
+ {{ $authors }}
+ {{- end -}}
+ {{- else -}}
+ Edited by:
+ {{ if reflect.IsSlice $editors -}}
+ {{ delimit $editors "; " "; and " }}
+ {{- else -}}
+ {{ $editors }}
+ {{- end -}}
+ {{- end -}}
+
+ {{- end -}}
+
{{- /* Safe date: use front matter date only if non-empty & matches basic pattern */ -}}
{{- $d := .Date -}}
{{- with .Params.date -}}
@@ -51,27 +82,28 @@
{{- $d = time $datestr -}}
{{- end -}}
{{- end }}
- {{ $d.Format "2006-01-02" }}
+ {{- $d = $d.Format "2006-01-02" -}}
+ {{- /* Don't display bogus date */ -}}
+ {{- if (ne $d "0001-01-01") }}
+ {{ $d }}
+ {{ end -}}
{{ with .Params.abstract -}}
- {{- $plain := . | plainify | htmlEscape | replaceRE `\s+` " " -}}
- {{- $words := split $plain " " -}}
- {{- $previewWords := cond (gt (len $words) 24) (first 24 $words) $words -}}
- {{- $preview := delimit $previewWords " " -}}
+ {{- /* can't plainify, as above */ -}}
+ {{- /* $plain := . | plainify | htmlEscape | replaceRE `\s+` " " */ -}}
+ {{- $plain := . | htmlEscape | replaceRE `\s+` " " -}}
+ {{- $previewing := gt (countwords $plain) $previewWordLimit -}}
+ {{- $preview := "" -}}
+ {{- if $previewing -}}
+ {{- $previewWords := split $plain " " | first $previewWordLimit -}}
+ {{- $preview = delimit $previewWords " " -}}
+ {{- else -}}
+ {{- $preview = replace . "\n" " " -}}
+ {{- end -}}
- {{ $preview | safeHTML }}{{ if gt (len $words) 24 }}…{{ end }}
+ {{ $preview | safeHTML }}{{ if $previewing }}…{{ end }}
{{- end -}}
-
- {{- $authors := .Params.authors -}}
- {{- /* warnf "authors: %v" $authors */ -}}
- {{- if $authors -}}
- {{- if reflect.IsSlice $authors -}}
- {{ delimit $authors "; " " and " }}
- {{- else -}}
- {{ $authors }}
- {{- end -}}
- {{- end -}}
{{ end }}
diff --git a/layouts/bibliography/single.html b/layouts/bibliography/single.html
index 52361ca9..df1d70ca 100644
--- a/layouts/bibliography/single.html
+++ b/layouts/bibliography/single.html
@@ -2,26 +2,53 @@
{{ .Title }}
+{{- $authors := .Params.authors -}}
+{{- $editors := .Params.editors -}}
+{{- $isPatent := eq .Params.item_type "patent" -}}
+{{- if or $authors $editors -}} {{- /* no empty if neither */ -}}
-{{- if .Params.authors -}}
- {{- if reflect.IsSlice .Params.authors -}}
- {{ delimit .Params.authors ", " " and " }}
+ {{- if $authors -}}
+ {{- if reflect.IsSlice $authors -}}
+ {{- if $isPatent }}
+ Inventors:
+ {{ end }}
+ {{ delimit $authors "; " "; and " }}
{{- else -}}
- {{ .Params.authors }}
+ {{- if $isPatent }}
+ Inventor:
+ {{ end }}
+ {{ $authors }}
{{- end -}}
+ {{- else -}}
+ Edited by:
+ {{ if reflect.IsSlice $editors }}
+ {{ delimit $editors "; " "; and " }}
+ {{- else }}
+ {{ $editors }}
+ {{- end -}}
+ {{- end -}}
+
{{- end -}}
-
{{- $d := .Date -}}
- {{- with .Params.date }}{{ $d = time . }}{{ end }}
- {{ $d.Format "2006-01-02" }}
+ {{- with .Params.date -}}
+ {{- $datestr := trim . " " -}}
+ {{- if and (ne $datestr "") (findRE `^\d{4}-\d{2}-\d{2}` $datestr) -}}
+ {{- $d = time $datestr -}}
+ {{- end -}}
+ {{- end }}
+ {{- $d = $d.Format "2006-01-02" -}}
+ {{- /* Don't display bogus date */ -}}
+ {{- if (ne $d "0001-01-01") }}
+ {{ $d }}
+ {{ end -}}
- URL: {{ with .Params.url_source }}
+ View document: {{ with .Params.url_source }}
{{ . }}
{{ else }}
- No URL available.
+ No URL to the document is available.
{{ end }}
Cite: placeholder for link to retrieve citation from Zotero
diff --git a/scripts/bib-fns.jq b/scripts/bib-fns.jq
index 6de5ce07..4fc0151b 100644
--- a/scripts/bib-fns.jq
+++ b/scripts/bib-fns.jq
@@ -30,12 +30,7 @@ def issued_iso_string:
.
end;
-# Build ["Family, Given", "Family2, Given2", ...] string array from .author array.
-# Falls back to other common shapes (name / firstName+lastName). Skips empty parts.
-def author_string_list:
- ( .author // [] )
- | dbg("author_string_list.count"; length)
- | map(
+def format_person_name:
if (has("family") and .family != null and (.family|tostring|length)>0) then
.family
+ ( if (has("given") and .given != null and (.given|tostring|length)>0)
@@ -50,12 +45,28 @@ def author_string_list:
.name
else
empty
- end
- );
+ end;
+
+# Build ["Family, Given", "Family2, Given2", ...] string array from .author array.
+# Falls back to other common shapes (name / firstName+lastName). Skips empty parts.
+def author_string_list:
+ ( .author // [] )
+# | dbg("author_string_list.count"; length)
+ | map(format_person_name);
# If you want the field added into each item:
def add_author_string:
- . + { authorsFormatted: (author_string_list) };
+ if (.author) then . + { authorsFormatted: (author_string_list) } end;
+
+# Likewise for editors
+def editor_string_list:
+ ( .editor // [] )
+# | dbg("editor_string_list.count"; length)
+ | map(format_person_name);
+
+# If you want the field added into each item:
+def add_editor_string:
+ if (.editor) then. + { editorsFormatted: (editor_string_list) } end;
def make_DOI_to_url($doi):
if ($doi | startswith("https:")) then $doi else "https://doi.org/" + ($doi | ltrimstr("/")) end ;
@@ -139,3 +150,7 @@ def bibItem: # assumes that only one item is the input
. as $item
| (keys - ["key","title","target"]) as $tailKeys
| {"key": .key, "title": .title, "target": .target } + ($tailKeys | map(. as $tKey | {"key": $tKey, "value": ($item | getpath([$tKey]))}) | from_entries);
+
+
+def removeEmptyKeys:
+ with_entries(select(.value != "" and .value != null and .value != [] and .value != {}));
\ No newline at end of file
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index a4576482..33f743c8 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -58,6 +58,9 @@ BEGIN
# Abstracts can be multi-line and contain multiple paragraphs. Place YAML keyword on
# one line and follow it with the abstract indented on subsequent lines.
my $abs = sanitize_text($obj->{abstract} // '');
+ # a hack for bulleted lists in the abstracts (use markdown there)
+ # won't work for nested lists.
+ $abs =~ s/\n?\n\N{U+2022}/\n*/g;
my $indented = join('', map { " $_\n" } split(/\n/, $abs));
my $abstract = $indented eq '' ? "abstract: ''" : "abstract: |\n$indented";
@@ -72,6 +75,17 @@ BEGIN
}
$itemAuthors =~ s/\n$//; # strip trailing newline
}
+
+ my $itemEditors = '';
+ if (ref($obj->{editorsFormatted}) eq 'ARRAY' && @{$obj->{editorsFormatted}}) {
+ $itemEditors = "\n";
+ for my $a (@{$obj->{editorsFormatted}}) {
+ my $quoted = encode_json($a // '');
+ $itemEditors .= " - $quoted\n";
+ }
+ $itemEditors =~ s/\n$//; # strip trailing newline
+ }
+
my $urlSource = defined $obj->{url} ? $obj->{url} : '';
# optional fields - ones used vary by value of type
@@ -147,6 +161,7 @@ BEGIN
type: bibliography
item_type: $type
authors: $itemAuthors
+editors: $itemEditors
$abstract
$extraFields
diff --git a/scripts/update_bibliography.sh b/scripts/update_bibliography.sh
index 8ff3da57..554247b4 100755
--- a/scripts/update_bibliography.sh
+++ b/scripts/update_bibliography.sh
@@ -2,10 +2,10 @@
set -e
-rawItemsFile=false
+rawItemsFile=true
debugFiles=false
-tagFiles=false
-typeFiles=true
+tagFiles=true
+typeFiles=false
curlFiles=false
# The collection files will be created only if directly querying Zotero API.
collectionFiles=false
@@ -204,6 +204,7 @@ if $debugFiles ; then
fi
items=$(jq 'include "./bib-fns";map(getTargetInfo)' <<< "$items")
+items=$(jq 'include "./bib-fns";map(removeEmptyKeys)' <<< "$items")
# now use children items to amend the info for the parentItem
childrenGroupedByParent=$(jq 'group_by(.target)|map(sort_by(.parentItem))' <<< "$items")
@@ -267,6 +268,8 @@ finalCount=$(jq '. | length' <<< "$items")
items=$(jq 'include "./bib-fns";map(issued_iso_string)' <<< "$items")
items=$(jq 'include "./bib-fns";map(add_author_string)' <<< "$items")
+
+items=$(jq 'include "./bib-fns";map(add_editor_string)' <<< "$items")
# if $removeChildrenFromFinalFile; then
# # Remove .children arrays, if any. Save space.
# items=$(jq 'map(del(.children))' <<< "$items")
@@ -279,7 +282,6 @@ items=$(jq 'include "./bib-fns";map(add_author_string)' <<< "$items")
# Do this here, instead of keeping a copy of the current value of $items, just to do this later.
jq -c 'include "./bib-fns";.[] | bibItem' <<< "$items" > bibliography-items-by-line.json
-# jq 'include "./bib-fns";map(bibItem)' <<< "$items" > 000-bibliography-items-by-line.json
# Group by year
items=$(jq 'group_by(.issued."date-parts"[0][0])' <<< "$items")
From 92b7232b51b153ef8e8ce6d4ba374187ef72b719 Mon Sep 17 00:00:00 2001
From: Bill Stumbo
Date: Sun, 26 Oct 2025 00:24:05 -0400
Subject: [PATCH 21/23] Taxonomy support for filtering bibliographical entries
Add bibliographical support for item_type (the type of
bibliographic entry) and author.
Provide support for filtering bibliographic list by both
types of tags.
---
.github/workflows/gh-pages.yml | 2 +-
config/_default/hugo.yaml | 5 +-
config/_default/params.yaml | 31 ++-
config/_default/taxonomies.yaml | 9 +-
content/en/history/bibliography/_index.md | 4 +-
layouts/bibliography/baseof.html | 3 -
layouts/bibliography/list.html | 177 ++++++++-------
layouts/partials/taxonomy_terms_cloud.html | 21 ++
layouts/shortcodes/bibTable.html | 246 ---------------------
9 files changed, 150 insertions(+), 348 deletions(-)
create mode 100644 layouts/partials/taxonomy_terms_cloud.html
delete mode 100644 layouts/shortcodes/bibTable.html
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
index ed5ead6f..ba7c54d2 100644
--- a/.github/workflows/gh-pages.yml
+++ b/.github/workflows/gh-pages.yml
@@ -43,7 +43,7 @@ defaults:
env:
# ----------------------------------------------------------------------------
# Specify the deployment environment: staging or production
- HUGO_ENVIRONMENT: staging
+ HUGO_ENVIRONMENT: production
HUGO_VERSION: 0.144.2
jobs:
diff --git a/config/_default/hugo.yaml b/config/_default/hugo.yaml
index 09ff7a38..1eb6da3c 100644
--- a/config/_default/hugo.yaml
+++ b/config/_default/hugo.yaml
@@ -35,8 +35,9 @@ defaultContentLanguageInSubdir: false
enableMissingTranslationPlaceholders: true
# Disable rendering of the specified page kinds
-disableKinds:
- - term
+#disableKinds:
+# - term
+# Note terms are needed for taxonomies to work
outputs:
home:
diff --git a/config/_default/params.yaml b/config/_default/params.yaml
index fca92498..31f85c72 100644
--- a/config/_default/params.yaml
+++ b/config/_default/params.yaml
@@ -104,15 +104,26 @@ links:
# icon: "fa fa-envelope"
# desc: "Discuss development issues around the project"
-related:
- threshold: 80
- includeNewer: true
- toLower: true
- indices:
- - name: tags
- weight: 100
- - name: categories
- weight: 70
+taxonomy:
+ taxonomyCloud:
+ - authors
+ taxonomyCloudTitle:
+ - Authors
+ taxonomyPageHeader:
+ - authors
+ - item_type
+
+#related:
+# threshold: 80
+# includeNewer: true
+# toLower: true
+# indices:
+# - name: item_type
+# weight: 5
+# - name: tags
+# weight: 100
+# - name: categories
+# weight: 70
# Nothing defined
@@ -159,7 +170,7 @@ ui:
sidebar_cache_limit: 100
# We have almost 200 attributes; don't truncate the sidebar to max 50 contents.
- sidebar_menu_truncate: 1000
+ sidebar_menu_truncate: 0
# Set to true to disable breadcrumb navigation.
breadcrumb_disable: false
diff --git a/config/_default/taxonomies.yaml b/config/_default/taxonomies.yaml
index cf4dceb9..b6bb7949 100644
--- a/config/_default/taxonomies.yaml
+++ b/config/_default/taxonomies.yaml
@@ -1,5 +1,4 @@
-taxonomies:
- tag: tags
- category: categories
- author: authors
- item_type: item_type
\ No newline at end of file
+tag: tags
+category: categories
+author: authors
+item_type: item_type
\ No newline at end of file
diff --git a/content/en/history/bibliography/_index.md b/content/en/history/bibliography/_index.md
index 9f56fe8a..af682331 100644
--- a/content/en/history/bibliography/_index.md
+++ b/content/en/history/bibliography/_index.md
@@ -1,5 +1,6 @@
---
title: Bibliography
+heading: Interlisp Bibliography
type: bibliography
cascade:
type: bibliography
@@ -8,7 +9,4 @@ aliases:
- /bibliography/
---
-
-# Interlisp Bibliography
-
(This bibliography is kept in sync with our [Zotero](https://www.zotero.org/) collection [Library](https://www.zotero.org/groups/2914042/interlisp/library).
diff --git a/layouts/bibliography/baseof.html b/layouts/bibliography/baseof.html
index 5f5bec26..ebd44c94 100644
--- a/layouts/bibliography/baseof.html
+++ b/layouts/bibliography/baseof.html
@@ -13,9 +13,6 @@