diff options
Diffstat (limited to 'scripts/metadata_filter.lua')
-rw-r--r-- | scripts/metadata_filter.lua | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/scripts/metadata_filter.lua b/scripts/metadata_filter.lua new file mode 100644 index 0000000..f31bc1f --- /dev/null +++ b/scripts/metadata_filter.lua | |||
@@ -0,0 +1,225 @@ | |||
1 | function format_date(date) | ||
2 | if date == nil then | ||
3 | return date | ||
4 | end | ||
5 | |||
6 | date = pandoc.utils.normalize_date(pandoc.utils.stringify(date)) | ||
7 | local year, month, day = date:match("(%d%d%d%d)-(%d%d)-(%d%d)") | ||
8 | if year == nil then | ||
9 | return nil | ||
10 | end | ||
11 | |||
12 | local time = os.time({ | ||
13 | year = tonumber(year), | ||
14 | month = tonumber(month), | ||
15 | day = tonumber(day) | ||
16 | }) | ||
17 | return pandoc.MetaMap({ | ||
18 | yyyy_mm_dd = pandoc.MetaString(os.date("%F", time)), | ||
19 | yyyy = pandoc.MetaString(os.date("%Y", time)), | ||
20 | mm_dd = pandoc.MetaString(os.date("%m-%d", time)), | ||
21 | rfc3339 = pandoc.MetaString(os.date("%FT%T+00:00", time)) | ||
22 | }) | ||
23 | end | ||
24 | |||
25 | function table_to_list(t, cmp) | ||
26 | local l = pandoc.MetaList({}) | ||
27 | |||
28 | for key, value in pairs(t) do | ||
29 | l:insert(pandoc.MetaMap({ | ||
30 | key = key, | ||
31 | value = value | ||
32 | })) | ||
33 | end | ||
34 | |||
35 | l:sort(cmp or function(i1, i2) | ||
36 | return i1.key < i2.key | ||
37 | end) | ||
38 | |||
39 | return l | ||
40 | end | ||
41 | |||
42 | function splitstr(input, sep) | ||
43 | sep = sep or "%s" | ||
44 | local t = {} | ||
45 | for str in input:gmatch("([^" .. sep .. "]+)") do | ||
46 | table.insert(t, str) | ||
47 | end | ||
48 | return t | ||
49 | end | ||
50 | |||
51 | function relative_to(dir, target) | ||
52 | dir = splitstr(dir, "/") | ||
53 | target = splitstr(target, "/") | ||
54 | |||
55 | local prefix = true | ||
56 | local path = "" | ||
57 | |||
58 | for i = 1, math.min(#dir, #target) do | ||
59 | local t = target[i] | ||
60 | if prefix then | ||
61 | if dir[i] ~= t then | ||
62 | prefix = false | ||
63 | path = "../" .. t | ||
64 | end | ||
65 | else | ||
66 | path = "../" .. path .. "/" .. t | ||
67 | end | ||
68 | end | ||
69 | |||
70 | if #dir < #target then | ||
71 | for i = #dir + 1, #target do | ||
72 | path = path .. (path == "" and "" or "/") .. target[i] | ||
73 | end | ||
74 | elseif #dir > #target then | ||
75 | for i = #target + 1, #dir do | ||
76 | path = "../" .. path | ||
77 | end | ||
78 | end | ||
79 | |||
80 | return path | ||
81 | end | ||
82 | |||
83 | function resolve_url(page_type, site_url, content_dir, base_dir, cur_file) | ||
84 | if page_type == "page" then | ||
85 | cur_file = cur_file:gsub("%.md$", ".html") | ||
86 | elseif page_type == "feed" then | ||
87 | cur_file = cur_file:gsub("%.md$", ".xml") | ||
88 | end | ||
89 | |||
90 | local abs = cur_file:gsub("^" .. content_dir, ""):gsub("/index.html$", "/") | ||
91 | local rel = relative_to(base_dir, cur_file):gsub("/index.html$", "/") | ||
92 | |||
93 | return pandoc.MetaMap({ | ||
94 | abs = pandoc.MetaString(abs), | ||
95 | rel = pandoc.MetaString(rel), | ||
96 | full = pandoc.MetaString(site_url .. abs) | ||
97 | }) | ||
98 | end | ||
99 | |||
100 | function resolve_section(abs_url) | ||
101 | local section = abs_url:match("^/(.-)[/.]") or "index" | ||
102 | return pandoc.MetaMap({ | ||
103 | id = pandoc.MetaString(section), | ||
104 | ["is_" .. section] = pandoc.MetaBool(true) | ||
105 | }) | ||
106 | end | ||
107 | |||
108 | function organize_subpages(site_url, content_dir, base_dir, pages, categories) | ||
109 | local categories_data = pandoc.MetaList({}) | ||
110 | |||
111 | pages:sort(function(p1, p2) | ||
112 | if p1.date and p2.date then | ||
113 | return pandoc.utils.stringify(p1.date.yyyy_mm_dd) > pandoc.utils.stringify(p2.date.yyyy_mm_dd) | ||
114 | elseif p2.date then | ||
115 | return true | ||
116 | elseif p1.date then | ||
117 | return false | ||
118 | else | ||
119 | return pandoc.utils.stringify(p1.title) < pandoc.utils.stringify(p2.title) | ||
120 | end | ||
121 | end) | ||
122 | |||
123 | local pages_data = pandoc.MetaMap({ | ||
124 | all = pages, | ||
125 | by_year = pandoc.MetaList({}), | ||
126 | last_update = nil | ||
127 | }) | ||
128 | |||
129 | if pages then | ||
130 | local pages_by_year_map = {} | ||
131 | local categories_map = {} | ||
132 | |||
133 | for i = 1, #pages do | ||
134 | local page = pages[i] | ||
135 | |||
136 | if page.date then | ||
137 | local yyyy = pandoc.utils.stringify(page.date.yyyy) | ||
138 | local pages_by_yyyy = pages_by_year_map[yyyy] | ||
139 | |||
140 | if not pages_by_yyyy then | ||
141 | pages_by_yyyy = pandoc.MetaList(pandoc.List()) | ||
142 | pages_by_year_map[yyyy] = pages_by_yyyy | ||
143 | end | ||
144 | |||
145 | pages_by_yyyy:insert(page) | ||
146 | end | ||
147 | |||
148 | if page.category and categories then | ||
149 | local category = pandoc.utils.stringify(page.category) | ||
150 | |||
151 | if categories[category] then | ||
152 | local current_category = categories_map[category] | ||
153 | |||
154 | if not current_category then | ||
155 | current_category = pandoc.MetaMap({ | ||
156 | name = pandoc.MetaString(categories[category]), | ||
157 | count = 0 | ||
158 | }) | ||
159 | categories_map[category] = current_category | ||
160 | end | ||
161 | |||
162 | current_category.count = current_category.count + 1 | ||
163 | end | ||
164 | end | ||
165 | end | ||
166 | |||
167 | pages_data.by_year = table_to_list(pages_by_year_map, function(i1, i2) | ||
168 | return i1.key > i2.key | ||
169 | end) | ||
170 | |||
171 | categories_data = table_to_list(categories_map) | ||
172 | |||
173 | for _, item in ipairs(categories_data) do | ||
174 | item.value.count = pandoc.MetaString(("%d"):format(item.value.count)) | ||
175 | end | ||
176 | |||
177 | if #pages_data.by_year ~= 0 then | ||
178 | pages_data.last_update = pages_data.by_year[1].value[1].last_update | ||
179 | end | ||
180 | end | ||
181 | |||
182 | return pages_data, categories_data | ||
183 | end | ||
184 | |||
185 | function Meta(meta) | ||
186 | meta.content_dir = meta.content_dir:gsub("/$", "") | ||
187 | meta.site.url = pandoc.utils.stringify(meta.site.url):gsub("/$", "") | ||
188 | meta.base_dir = meta.base_file:gsub("^(.*)/.-$", "%1") | ||
189 | meta.type = meta.type or "page" | ||
190 | |||
191 | meta.date = format_date(meta.date) | ||
192 | if meta.last_update ~= nil then | ||
193 | meta.last_update = format_date(meta.last_update) | ||
194 | else | ||
195 | meta.last_update = meta.date | ||
196 | end | ||
197 | |||
198 | if meta.type == "feed" then | ||
199 | meta.page = pandoc.MetaMap({ | ||
200 | url = resolve_url("page", meta.site.url, meta.content_dir, meta.base_dir, meta.file) | ||
201 | }) | ||
202 | end | ||
203 | |||
204 | meta.url = resolve_url(meta.type, meta.site.url, meta.content_dir, meta.base_dir, meta.file) | ||
205 | meta.section = resolve_section(meta.url.abs) | ||
206 | meta.categories = meta.categories[meta.section.id] | ||
207 | |||
208 | if meta.menus and meta.menus.main then | ||
209 | for i = 1, #meta.menus.main do | ||
210 | local item = meta.menus.main[i] | ||
211 | item.active = pandoc.MetaBool(pandoc.utils.stringify(item.id) == meta.section.id) | ||
212 | end | ||
213 | end | ||
214 | |||
215 | if meta.pages then | ||
216 | local pages, categories = organize_subpages(meta.site.url, meta.content_dir, meta.base_dir, meta.pages, | ||
217 | meta.categories) | ||
218 | meta.pages = pages | ||
219 | meta.categories = categories | ||
220 | else | ||
221 | meta.categories = nil | ||
222 | end | ||
223 | |||
224 | return meta | ||
225 | end | ||