summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorVolpeon <git@volpeon.ink>2022-08-04 10:26:57 +0200
committerVolpeon <git@volpeon.ink>2022-08-04 10:26:57 +0200
commit347d7c0da13079fefce6d8741a5604adb89eb97c (patch)
tree43b568e5ae48692425a9ddeeddc4001b1e940336 /scripts
parentCode reorganization (diff)
downloadvolpeon.ink-347d7c0da13079fefce6d8741a5604adb89eb97c.tar.gz
volpeon.ink-347d7c0da13079fefce6d8741a5604adb89eb97c.tar.bz2
volpeon.ink-347d7c0da13079fefce6d8741a5604adb89eb97c.zip
Overhauled metadata handling
Diffstat (limited to 'scripts')
-rw-r--r--scripts/content.lua (renamed from scripts/pages_content.lua)2
-rw-r--r--scripts/lib/common.lua10
-rw-r--r--scripts/lib/sort.lua36
-rw-r--r--scripts/metadata.lua211
-rw-r--r--scripts/page.lua222
5 files changed, 290 insertions, 191 deletions
diff --git a/scripts/pages_content.lua b/scripts/content.lua
index b753b1e..d77759d 100644
--- a/scripts/pages_content.lua
+++ b/scripts/content.lua
@@ -4,7 +4,7 @@ local namespace = ''
4local siteUrl = '' 4local siteUrl = ''
5 5
6function meta(meta) 6function meta(meta)
7 namespace = pandoc.utils.stringify(meta.namespace.full) 7 namespace = pandoc.utils.stringify(meta.namespace)
8 siteUrl = pandoc.utils.stringify(meta.site.url):gsub("/$", "") 8 siteUrl = pandoc.utils.stringify(meta.site.url):gsub("/$", "")
9end 9end
10 10
diff --git a/scripts/lib/common.lua b/scripts/lib/common.lua
index 80b81ba..5ed3e31 100644
--- a/scripts/lib/common.lua
+++ b/scripts/lib/common.lua
@@ -49,6 +49,16 @@ function pandoc.List:take(n)
49 return result 49 return result
50end 50end
51 51
52function pandoc.List:skip(n)
53 local result = pandoc.List()
54
55 if n >= #self then return result end
56
57 for i = n + 1, #self do result:insert(self[i]) end
58
59 return result
60end
61
52return { 62return {
53 dump = dump 63 dump = dump
54} 64}
diff --git a/scripts/lib/sort.lua b/scripts/lib/sort.lua
new file mode 100644
index 0000000..393e5d5
--- /dev/null
+++ b/scripts/lib/sort.lua
@@ -0,0 +1,36 @@
1local utils = require 'pandoc.utils'
2
3function page_sort(order, pages)
4 order = order and utils.stringify(order)
5
6 return function(ref1, ref2)
7 local p1 = pages and pages[utils.stringify(ref1)] or ref1
8 local p2 = pages and pages[utils.stringify(ref2)] or ref2
9
10 if p1.position then
11 if p2.position then
12 return tonumber(utils.stringify(p1.position)) < tonumber(utils.stringify(p2.position))
13 else
14 return true
15 end
16 elseif p2.position then
17 return false
18 elseif order == "date_desc" then
19 if p1.last_update then
20 if p2.last_update then
21 return utils.stringify(p1.last_update.yyyy_mm_dd) > utils.stringify(p2.last_update.yyyy_mm_dd)
22 else
23 return true
24 end
25 else
26 return false
27 end
28 else
29 return utils.stringify(p1.title):upper() < utils.stringify(p2.title):upper()
30 end
31 end
32end
33
34return {
35 page_sort = page_sort
36}
diff --git a/scripts/metadata.lua b/scripts/metadata.lua
index 6aa679a..5157677 100644
--- a/scripts/metadata.lua
+++ b/scripts/metadata.lua
@@ -1,31 +1,7 @@
1local path = require 'pandoc.path' 1local path = require 'pandoc.path'
2local utils = require 'pandoc.utils'
2local common = require 'scripts.lib.common' 3local common = require 'scripts.lib.common'
3 4local sort = require 'scripts.lib.sort'
4function page_sort(order)
5 return function(p1, p2)
6 if p1.position then
7 if p2.position then
8 return p1.position < p2.position
9 else
10 return true
11 end
12 elseif p2.position then
13 return false
14 elseif order == "date_desc" then
15 if p1.last_update then
16 if p2.last_update then
17 return p1.last_update.yyyy_mm_dd > p2.last_update.yyyy_mm_dd
18 else
19 return true
20 end
21 else
22 return false
23 end
24 else
25 return p1.title:upper() < p2.title:upper()
26 end
27 end
28end
29 5
30function slug(str) 6function slug(str)
31 return str:lower():gsub("[^ a-z]", ""):gsub("[ ]+", "-") 7 return str:lower():gsub("[^ a-z]", ""):gsub("[ ]+", "-")
@@ -34,7 +10,7 @@ end
34function format_date(date) 10function format_date(date)
35 if not date then return date end 11 if not date then return date end
36 12
37 date = pandoc.utils.normalize_date(pandoc.utils.stringify(date)) 13 date = pandoc.utils.normalize_date(utils.stringify(date))
38 local year, month, day = date:match("(%d%d%d%d)-(%d%d)-(%d%d)") 14 local year, month, day = date:match("(%d%d%d%d)-(%d%d)-(%d%d)")
39 if not year then return nil end 15 if not year then return nil end
40 16
@@ -54,17 +30,6 @@ function make_absolute(rel, base)
54 return path.is_absolute(rel) and rel or path.join({ path.directory(base), rel }) 30 return path.is_absolute(rel) and rel or path.join({ path.directory(base), rel })
55end 31end
56 32
57function resolve_url(site_url, ref_file, target_file)
58 target_file = target_file:gsub("/index%.html$", "/")
59
60 local ref_base_dir = path.directory(ref_file)
61 local abs = target_file
62 local rel = path.make_relative(abs, ref_base_dir, true)
63 local full = (abs:sub(1, 1) == "/" and (site_url .. abs)) or abs
64
65 return { abs = abs, rel = rel, full = full }
66end
67
68function resolve_layout(depth) 33function resolve_layout(depth)
69 local layout = "categorized_list" 34 local layout = "categorized_list"
70 35
@@ -78,12 +43,12 @@ function resolve_layout(depth)
78end 43end
79 44
80function prep_layout(layout) 45function prep_layout(layout)
81 layout = pandoc.utils.stringify(layout) 46 layout = utils.stringify(layout)
82 return { id = layout, ["is_" .. layout] = true } 47 return { id = layout, ["is_" .. layout] = true }
83end 48end
84 49
85function resolve_namespace(namespace) 50function prep_namespace(namespace)
86 namespace = pandoc.utils.stringify(namespace) 51 namespace = utils.stringify(namespace)
87 52
88 local root = "index" 53 local root = "index"
89 if namespace ~= "" then root = namespace:gsub("^/([^/]*).*$", "%1") end 54 if namespace ~= "" then root = namespace:gsub("^/([^/]*).*$", "%1") end
@@ -97,7 +62,7 @@ function prep_menu(active_id, main_menu)
97 62
98 for i = 1, #main_menu do 63 for i = 1, #main_menu do
99 local item = main_menu[i] 64 local item = main_menu[i]
100 local active = pandoc.utils.stringify(item.id) == active_id 65 local active = utils.stringify(item.id) == active_id
101 item.active = active 66 item.active = active
102 if active then active_item = item end 67 if active then active_item = item end
103 if not item.hidden or item.active then items:insert(item) end 68 if not item.hidden or item.active then items:insert(item) end
@@ -107,22 +72,20 @@ function prep_menu(active_id, main_menu)
107end 72end
108 73
109function process_pages(global, build, meta) 74function process_pages(global, build, meta)
110 local order = meta.list_order
111
112 local pages_all = pandoc.List() 75 local pages_all = pandoc.List()
113 local pages_date_desc = pandoc.List() 76 local pages_date_desc = pandoc.List()
114 77
115 for _, p in pairs(meta.pages) do 78 for id, p in pairs(meta.pages) do
116 process(global, build, p) 79 process(global, build, p)
117 80
118 if not p.unlisted then 81 if not p.unlisted then
119 pages_all:insert(p) 82 pages_all:insert(id)
120 if p.last_update then pages_date_desc:insert(p) end 83 if p.last_update then pages_date_desc:insert(id) end
121 end 84 end
122 end 85 end
123 86
124 pages_all:sort(page_sort(order)) 87 pages_all:sort(sort.page_sort(meta.list_order, meta.pages))
125 pages_date_desc:sort(page_sort("date_desc")) 88 pages_date_desc:sort(sort.page_sort("date_desc", meta.pages))
126 89
127 meta.pages = { all = pages_all, date_desc = pages_date_desc, by_id = meta.pages } 90 meta.pages = { all = pages_all, date_desc = pages_date_desc, by_id = meta.pages }
128end 91end
@@ -145,35 +108,11 @@ function find_depth(meta)
145 meta.depth = depth 108 meta.depth = depth
146end 109end
147 110
148function resolve_urls(global, build, meta)
149 meta.url = resolve_url(global.site.url, build.file_out, meta.url)
150
151 if meta.feed then
152 if meta.file_out:match(".html$") then
153 meta.feed = {
154 url = resolve_url(global.site.url, build.file_out, meta.file_out:gsub(".html$", ".xml")),
155 }
156 else
157 meta.page = {
158 url = resolve_url(global.site.url, build.file_out, meta.file_out:gsub(".xml$", ".html")),
159 }
160 end
161 end
162
163 if meta.thumbnail then
164 meta.thumbnail = resolve_url(global.site.url, build.file_out, meta.thumbnail)
165 end
166
167 -- for _, p in pairs(meta.pages.by_id) do
168 -- resolve_urls(global, build, p)
169 -- end
170end
171
172function resolve_dates(meta) 111function resolve_dates(meta)
173 if meta.last_update then 112 if meta.last_update then
174 meta.last_update = format_date(meta.last_update) 113 meta.last_update = format_date(meta.last_update)
175 elseif #meta.pages.date_desc ~= 0 then 114 elseif #meta.pages.date_desc ~= 0 then
176 meta.last_update = meta.pages.date_desc[1].last_update 115 meta.last_update = meta.pages.by_id[meta.pages.date_desc[1]].last_update
177 elseif meta.date then 116 elseif meta.date then
178 meta.last_update = format_date(meta.date) 117 meta.last_update = format_date(meta.date)
179 end 118 end
@@ -187,125 +126,23 @@ function resolve_dates(meta)
187 meta.was_updated = meta.date and meta.last_update and meta.date.yyyy_mm_dd ~= meta.last_update.yyyy_mm_dd 126 meta.was_updated = meta.date and meta.last_update and meta.date.yyyy_mm_dd ~= meta.last_update.yyyy_mm_dd
188end 127end
189 128
190function d1_page_to_list_item(meta, p)
191 return {
192 title = p.title,
193 subtitle = p.subtitle,
194 date = p.date,
195 last_update = p.last_update,
196 show_date = meta.list_order == "date_desc",
197 schema_type = p.schema_type,
198 draft = p.draft,
199 position = p.position,
200 url = p.url,
201 rel = p.rel,
202 slug = p.slug,
203 thumbnail = p.thumbnail,
204 icon = p.icon or meta.icon,
205 post_icon = p.post_icon or meta.list_post_icon,
206 indicator = meta.list_read_indicators,
207 }
208end
209
210function d2_page_to_list_item(meta, cat, p, set_cat_title)
211 return {
212 title = p.title,
213 subtitle = p.subtitle,
214 category = set_cat_title and cat.title,
215 date = p.date,
216 last_update = p.last_update,
217 show_date = cat.list_order == "date_desc",
218 schema_type = p.schema_type,
219 draft = p.draft,
220 position = p.position,
221 url = p.url,
222 rel = p.rel,
223 slug = p.slug,
224 thumbnail = p.thumbnail,
225 icon = p.icon or cat.icon,
226 post_icon = p.post_icon or cat.list_post_icon or meta.list_post_icon,
227 indicator = cat.list_read_indicators,
228 }
229end
230
231function cat_to_list_cat(cat, allItems)
232 local limit = cat.list_limit or 9999
233 local items = allItems:take(limit)
234 local omitted = #allItems - #items
235
236 return {
237 title = cat.title,
238 description = (cat.description and pandoc.MetaBlocks(pandoc.Para(cat.description))) or
239 (not cat.no_description and cat.content),
240 last_update = cat.last_update,
241 schema_type = cat.schema_type,
242 url = cat.url,
243 slug = cat.slug,
244 layout = cat.list_layout,
245 items = items,
246 total = tostring(#allItems),
247 omitted = omitted ~= 0 and tostring(omitted),
248 }
249end
250
251function generate_list(meta)
252 if meta.depth < 1 then return pandoc.List() end
253
254 if meta.depth == 1 then
255 return meta.pages.all:map(function(p) return d1_page_to_list_item(meta, p) end)
256 end
257
258 if meta.depth == 2 then
259 return meta.pages.all
260 :map(function(cat)
261 local allItems = cat.pages.all:map(function(p) return d2_page_to_list_item(meta, cat, p, false) end)
262
263 return cat_to_list_cat(cat, allItems)
264 end)
265 :filter(function(cat) return #cat.items ~= 0 end)
266 end
267
268 if meta.depth == 3 then
269 local list = meta.pages.all
270 :map(function(cat)
271 local allItems = cat.pages.all:flatMap(function(c)
272 if cat.list_flatten and c.depth ~= 0 then
273 return c.pages.all:map(function(p) return d2_page_to_list_item(cat, c, p, true) end)
274 else
275 return pandoc.List({ d1_page_to_list_item(cat, c) })
276 end
277 end)
278
279 allItems:sort(page_sort(cat.list_order))
280
281 return cat_to_list_cat(cat, allItems)
282 end)
283 :filter(function(cat) return #cat.items ~= 0 end)
284
285 return list
286 end
287end
288
289function process_base(build, meta) 129function process_base(build, meta)
290 meta.namespace = resolve_namespace(meta.namespace) 130 meta.namespace = prep_namespace(meta.namespace)
291 meta.file_out = pandoc.utils.stringify(meta.file_out) 131 meta.file_out = utils.stringify(meta.file_out)
292 meta.unlisted = meta.unlisted or (meta.draft and build.mode ~= "dev") 132 meta.unlisted = meta.unlisted or (meta.draft and build.mode ~= "dev")
293 meta.redirect = meta.url and true 133 meta.redirect = meta.url and true
294 meta.url = meta.url and pandoc.utils.stringify(meta.url) or meta.file_out 134 meta.url = meta.url or meta.file_out
295 meta.title = meta.title and pandoc.utils.stringify(meta.title) or "" 135 meta.title = meta.title and utils.stringify(meta.title) or ""
296 meta.slug = slug(meta.title) 136 meta.slug = slug(meta.title)
297 meta.schema_type = meta.schema_type and pandoc.utils.stringify(meta.schema_type) or "CreativeWork" 137 meta.schema_type = meta.schema_type or "CreativeWork"
298 meta.list_order = meta.list_order and pandoc.utils.stringify(meta.list_order)
299 meta.list_layout = prep_layout(meta.list_layout or "list") 138 meta.list_layout = prep_layout(meta.list_layout or "list")
300 meta.list_limit = meta.list_limit and tonumber(pandoc.utils.stringify(meta.list_limit)) 139 meta.position = meta.position and tonumber(utils.stringify(meta.position))
301 meta.position = meta.position and tonumber(pandoc.utils.stringify(meta.position)) 140 meta.thumbnail = meta.thumbnail and make_absolute("thumbnail." .. utils.stringify(meta.thumbnail), meta.file_out)
302 meta.thumbnail = meta.thumbnail and make_absolute("thumbnail." .. pandoc.utils.stringify(meta.thumbnail), meta.file_out)
303 meta.layout = prep_layout(meta.layout or (meta.redirect and "redirect") or resolve_layout(meta.depth)) 141 meta.layout = prep_layout(meta.layout or (meta.redirect and "redirect") or resolve_layout(meta.depth))
304end 142end
305 143
306function process(global, build, meta) 144function process(global, build, meta)
307 process_base(build, meta) 145 process_base(build, meta)
308 resolve_urls(global, build, meta)
309 process_pages(global, build, meta) 146 process_pages(global, build, meta)
310 resolve_dates(meta) 147 resolve_dates(meta)
311end 148end
@@ -322,16 +159,10 @@ function Meta(meta)
322 end 159 end
323 end 160 end
324 161
325 meta.site.url = pandoc.utils.stringify(meta.site.url):gsub("/$", "") 162 meta.site.url = utils.stringify(meta.site.url):gsub("/$", "")
326 163
327 find_depth(meta) 164 find_depth(meta)
328 process(meta, build, meta) 165 process(meta, build, meta)
329 166
330 meta.list = generate_list(meta)
331
332 if meta.menus and meta.menus.main then
333 meta.menus.main = prep_menu(meta.namespace.root.id, meta.menus.main)
334 end
335
336 return meta 167 return meta
337end 168end
diff --git a/scripts/page.lua b/scripts/page.lua
new file mode 100644
index 0000000..e846dd5
--- /dev/null
+++ b/scripts/page.lua
@@ -0,0 +1,222 @@
1local path = require 'pandoc.path'
2local utils = require 'pandoc.utils'
3local common = require 'scripts.lib.common'
4local sort = require 'scripts.lib.sort'
5
6function resolve_url(site_url, ref_file, target_file)
7 site_url = utils.stringify(site_url)
8 ref_file = utils.stringify(ref_file)
9 target_file = utils.stringify(target_file):gsub("/index%.html$", "/")
10
11 local ref_base_dir = path.directory(ref_file)
12 local abs = target_file
13 local rel = path.make_relative(abs, ref_base_dir, true)
14 local full = (abs:sub(1, 1) == "/" and (site_url .. abs)) or abs
15
16 return { abs = abs, rel = rel, full = full }
17end
18
19function prep_menu(active_id, main_menu)
20 active_id = utils.stringify(active_id)
21
22 local active_item = nil
23 local items = pandoc.List()
24
25 for i = 1, #main_menu do
26 local item = main_menu[i]
27 local active = utils.stringify(item.id) == active_id
28 item.active = active
29 if active then active_item = item end
30 if not item.hidden or item.active then items:insert(item) end
31 end
32
33 return { items = items, active = active_item }
34end
35
36function process_pages(global, build, meta)
37 for _, p in pairs(meta.pages.by_id) do
38 process(global, build, p)
39 end
40
41 meta.pages = {
42 all = meta.pages.all:map(utils.stringify):map(function (ref) return meta.pages.by_id[ref] end),
43 date_desc = meta.pages.date_desc:map(utils.stringify):map(function (ref) return meta.pages.by_id[ref] end),
44 by_id = meta.pages.by_id
45 }
46end
47
48function resolve_urls(global, build, meta)
49 meta.url = resolve_url(global.site.url, build.file_out, meta.url)
50
51 if meta.feed then
52 if meta.file_out:match(".html$") then
53 meta.feed = {
54 url = resolve_url(global.site.url, build.file_out, meta.file_out:gsub(".html$", ".xml")),
55 }
56 else
57 meta.page = {
58 url = resolve_url(global.site.url, build.file_out, meta.file_out:gsub(".xml$", ".html")),
59 }
60 end
61 end
62
63 if meta.thumbnail then
64 meta.thumbnail = resolve_url(global.site.url, build.file_out, meta.thumbnail)
65 end
66end
67
68function d1_page_to_list_item(meta, p)
69 return {
70 title = p.title,
71 subtitle = p.subtitle,
72 date = p.date,
73 last_update = p.last_update,
74 show_date = meta.list_order == "date_desc",
75 schema_type = p.schema_type,
76 draft = p.draft,
77 position = p.position,
78 url = p.url,
79 rel = p.rel,
80 slug = p.slug,
81 thumbnail = p.thumbnail,
82 icon = p.icon or meta.icon,
83 post_icon = p.post_icon or meta.list_post_icon,
84 indicator = meta.list_read_indicators,
85 }
86end
87
88function d2_page_to_list_item(meta, cat, p, set_cat_title)
89 return {
90 title = p.title,
91 subtitle = p.subtitle,
92 category = set_cat_title and cat.title,
93 date = p.date,
94 last_update = p.last_update,
95 show_date = cat.list_order == "date_desc",
96 schema_type = p.schema_type,
97 draft = p.draft,
98 position = p.position,
99 url = p.url,
100 rel = p.rel,
101 slug = p.slug,
102 thumbnail = p.thumbnail,
103 icon = p.icon or cat.icon,
104 post_icon = p.post_icon or cat.list_post_icon or meta.list_post_icon,
105 indicator = cat.list_read_indicators,
106 }
107end
108
109function cat_to_list_cat(cat, allItems)
110 local limit = cat.list_limit or 9999
111 local items = allItems:take(limit)
112 local omitted = #allItems - #items
113
114 return {
115 title = cat.title,
116 description = (cat.description and pandoc.MetaBlocks(pandoc.Para(cat.description))) or
117 (not cat.no_description and cat.content),
118 last_update = cat.last_update,
119 schema_type = cat.schema_type,
120 url = cat.url,
121 slug = cat.slug,
122 layout = cat.list_layout,
123 items = items,
124 total = tostring(#allItems),
125 omitted = omitted ~= 0 and tostring(omitted),
126 }
127end
128
129function generate_list(meta)
130 if meta.depth < 1 then return pandoc.List() end
131
132 if meta.depth == 1 then
133 return meta.pages.all:map(function(p) return d1_page_to_list_item(meta, p) end)
134 end
135
136 if meta.depth == 2 then
137 return meta.pages.all
138 :map(function(cat)
139 local allItems = cat.pages.all:map(function(p) return d2_page_to_list_item(meta, cat, p, false) end)
140
141 return cat_to_list_cat(cat, allItems)
142 end)
143 :filter(function(cat) return #cat.items ~= 0 end)
144 end
145
146 if meta.depth == 3 then
147 local list = meta.pages.all
148 :map(function(cat)
149 local allItems = cat.pages.all:flatMap(function(c)
150 if cat.list_flatten and c.depth ~= 0 then
151 return c.pages.all:map(function(p) return d2_page_to_list_item(cat, c, p, true) end)
152 else
153 return pandoc.List({ d1_page_to_list_item(cat, c) })
154 end
155 end)
156
157 allItems:sort(sort.page_sort(cat.list_order))
158
159 return cat_to_list_cat(cat, allItems)
160 end)
161 :filter(function(cat) return #cat.items ~= 0 end)
162
163 return list
164 end
165end
166
167function process_base(meta)
168 meta.depth = tonumber(utils.stringify(meta.depth))
169 meta.file_out = utils.stringify(meta.file_out)
170 meta.url = utils.stringify(meta.url)
171 meta.title = utils.stringify(meta.title)
172 meta.list_limit = meta.list_limit and tonumber(utils.stringify(meta.list_limit))
173 meta.list_order = meta.list_order and utils.stringify(meta.list_order)
174 meta.position = meta.position and tonumber(utils.stringify(meta.position))
175 meta.thumbnail = meta.thumbnail and utils.stringify(meta.thumbnail)
176end
177
178function process(global, build, meta)
179 process_base(meta)
180 resolve_urls(global, build, meta)
181 process_pages(global, build, meta)
182end
183
184function Meta(meta)
185 local build = {}
186
187 for key, value in pairs(meta) do
188 local suffix = key:match('^build.(.*)$')
189
190 if suffix then
191 build[suffix] = value
192 meta[key] = nil
193 end
194 end
195
196 local global = {
197 assets = meta.assets,
198 site = meta.site,
199 menus = meta.menus
200 }
201
202 process(global, build, meta)
203
204 local parts = utils.stringify(build.namespace):split('/'):skip(1)
205 for i = 1, #parts do
206 meta = meta.pages.by_id[parts[i]]
207 end
208
209 meta.list = generate_list(meta)
210
211 if global.menus and global.menus.main then
212 global.menus.main = prep_menu(meta.namespace.root.id, global.menus.main)
213 end
214
215 for key, value in pairs(global) do
216 meta[key] = value
217 end
218
219 meta.build = build
220
221 return meta
222end