diff options
Diffstat (limited to 'scripts/page.lua')
-rw-r--r-- | scripts/page.lua | 222 |
1 files changed, 222 insertions, 0 deletions
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 @@ | |||
1 | local path = require 'pandoc.path' | ||
2 | local utils = require 'pandoc.utils' | ||
3 | local common = require 'scripts.lib.common' | ||
4 | local sort = require 'scripts.lib.sort' | ||
5 | |||
6 | function 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 } | ||
17 | end | ||
18 | |||
19 | function 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 } | ||
34 | end | ||
35 | |||
36 | function 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 | } | ||
46 | end | ||
47 | |||
48 | function 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 | ||
66 | end | ||
67 | |||
68 | function 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 | } | ||
86 | end | ||
87 | |||
88 | function 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 | } | ||
107 | end | ||
108 | |||
109 | function 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 | } | ||
127 | end | ||
128 | |||
129 | function 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 | ||
165 | end | ||
166 | |||
167 | function 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) | ||
176 | end | ||
177 | |||
178 | function process(global, build, meta) | ||
179 | process_base(meta) | ||
180 | resolve_urls(global, build, meta) | ||
181 | process_pages(global, build, meta) | ||
182 | end | ||
183 | |||
184 | function 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 | ||
222 | end | ||