-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcodex.lua
More file actions
188 lines (160 loc) · 5.14 KB
/
codex.lua
File metadata and controls
188 lines (160 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
-- codex.lua
-- Pandoc custom writer for Codex Document Format
--
-- Usage:
-- pandoc input.md -t codex.lua -o output.json
--
-- Output: JSON containing manifest, content, and dublin_core sections
-- that can be unpacked into a Codex directory structure and packaged.
-- Get the directory containing this script
local script_dir = PANDOC_SCRIPT_FILE and (PANDOC_SCRIPT_FILE:match("(.*/)" ) or "") or ""
-- Load library modules
local function load_lib(name)
local paths = {
script_dir .. "lib/" .. name .. ".lua",
"lib/" .. name .. ".lua",
"cdx-pandoc/lib/" .. name .. ".lua",
}
for _, path in ipairs(paths) do
local f = io.open(path, "r")
if f then
f:close()
return dofile(path)
end
end
error("Cannot find library: " .. name)
end
local json = load_lib("json")
local utils = load_lib("utils")
local inlines = load_lib("inlines")
local blocks = load_lib("blocks")
local metadata = load_lib("metadata")
local bibliography = load_lib("bibliography")
local academic = load_lib("academic")
-- Extension tracker
local extensions_used = {}
local function track_extension(ext_id)
extensions_used[ext_id] = true
end
-- Initialize blocks module with inlines reference
blocks.set_inlines(inlines)
blocks.set_extension_tracker(track_extension)
inlines.set_extension_tracker(track_extension)
-- Initialize academic module
academic.set_blocks(blocks)
academic.set_extension_tracker(track_extension)
blocks.set_academic(academic)
-- Spec version
local CODEX_VERSION = "0.1"
local CONTENT_VERSION = "0.7.1"
-- Generate ISO 8601 timestamp
local function iso_timestamp()
return os.date("!%Y-%m-%dT%H:%M:%SZ")
end
-- SHA-256 placeholder (actual hash computed by packaging tool)
local function placeholder_hash()
return "sha256:0000000000000000000000000000000000000000000000000000000000000000"
end
-- Create manifest structure
local function create_manifest()
local now = iso_timestamp()
return {
codex = CODEX_VERSION,
id = "pending",
state = "draft",
created = now,
modified = now,
content = {
path = "content/document.json",
hash = placeholder_hash()
},
metadata = {
dublinCore = "metadata/dublin-core.json"
}
}
end
-- Create content structure from Pandoc blocks
local function create_content(doc_blocks)
return {
version = CONTENT_VERSION,
blocks = blocks.convert(doc_blocks)
}
end
-- Main writer function
-- Pandoc calls this with the full document
function Writer(doc, opts)
-- Reset extension tracker
extensions_used = {}
-- Extract metadata
local dublin_core = metadata.extract(doc.meta) or metadata.default_metadata()
-- Generate JSON-LD from Dublin Core
local jsonld = metadata.generate_jsonld(dublin_core)
-- Extract CSL bibliography entries and detect style
local csl_entries = bibliography.extract_from_meta(doc.meta)
local citation_style = bibliography.detect_style(doc.meta)
-- Set bibliography context for block conversion
blocks.set_bibliography_context(csl_entries, citation_style)
-- Convert blocks
local content = create_content(doc.blocks)
-- Append accumulated footnotes as semantic:footnote blocks
local footnotes = inlines.get_footnotes()
local has_footnotes = #footnotes > 0
if has_footnotes then
local footnote_blocks = blocks.convert_footnotes(footnotes)
for _, fb in ipairs(footnote_blocks) do
table.insert(content.blocks, fb)
end
end
-- Create manifest
local manifest = create_manifest()
-- Add JSON-LD reference to manifest if generated
if jsonld then
manifest.metadata.jsonLd = "metadata/jsonld.json"
end
-- Track semantic extension usage from citations/footnotes
local citation_refs = inlines.get_citation_refs()
local has_citations = next(citation_refs) ~= nil
if has_citations or has_footnotes then
track_extension(utils.EXT_SEMANTIC)
end
-- Build extensions list from tracker
if next(extensions_used) then
local ext_list = {}
-- Sort for deterministic output
local ext_ids = {}
for ext_id, _ in pairs(extensions_used) do
table.insert(ext_ids, ext_id)
end
table.sort(ext_ids)
for _, ext_id in ipairs(ext_ids) do
table.insert(ext_list, {
id = ext_id,
version = "0.1",
required = false
})
end
manifest.extensions = ext_list
end
-- Combine into output structure
local output = {
manifest = manifest,
content = content,
dublin_core = dublin_core
}
-- Add JSON-LD if generated
if jsonld then
output.jsonld = jsonld
end
-- Return pretty-printed JSON
return json.pretty(output)
end
-- Template (not used for custom writers, but required by some Pandoc versions)
function Template()
return "$body$"
end
-- Pandoc 3.x uses a different calling convention
-- If the global Writer function doesn't work, try the module return
return {
Writer = Writer,
Template = Template
}