-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathluaxml-sty.lua
155 lines (138 loc) · 5.36 KB
/
luaxml-sty.lua
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
--- Helper functions for the luaxml.sty package
--- @module luaxml-sty
--- @author Michal Hoftich <michal.h21@gmail.com
-- provide global object with all variables we will use
luaxml_sty = {
current = {
transformation = "default",
parameters = {}, -- "parameters" argument for transform:add_action
},
packages = {},
-- we want to support multiple transformation objects, they will be stored here
transformations = {},
}
luaxml_sty.packages.transform = require "luaxml-transform"
luaxml_sty.packages.domobject = require "luaxml-domobject"
-- declare default transformer, used if no explicit transformer is used in LuaXML LaTeX commands
luaxml_sty.transformations.default = luaxml_sty.packages.transform.new()
-- debuggind functions
function luaxml_sty.error(...)
local arg = {...}
print("LuaXML error: " .. table.concat(arg, " "))
end
luaxml_sty.do_debug = false
function luaxml_sty.debug(...)
if luaxml_sty.do_debug then
local arg = {...}
print("LuaXML: " .. table.concat(arg, " "))
end
end
--- Declare new transformer
---@param name string transformer name
---@return table transformer object
function luaxml_sty.declare_transformer(name)
luaxml_sty.transformations[name] = luaxml_sty.packages.transform.new()
return luaxml_sty.transformations[name]
end
--- Add luaxml-transform rule
--- @param current string transformer name, empty for the default object
--- @param selector string CSS selector to be used
--- @param rule string luaxml-transform rule
function luaxml_sty.add_rule(current, selector, rule)
if current == "" then
current = luaxml_sty.current.transformation
end
-- the +v parameter type in LaTeX replaces newlines with \obeyedline. we need to replace it back to newlines
rule = rule:gsub("\\obeyedline", "\n")
luaxml_sty.debug("************* luaxml_sty rule: " .. selector, rule, current, (luaxml_sty.current.parameters.verbatim and "verbatim" or "not verbatim"))
local transform = luaxml_sty.transformations[current] or luaxml_sty.declare_transformer(current)
if not transform then
luaxml_sty.error("Cannot find LuaXML transform object: " .. (current or ""))
return nil, "Cannot find LuaXML transform object: " .. (current or "")
end
transform:add_action(selector, rule, luaxml_sty.current.parameters)
end
-- by default, we will use XML parser, so use_xml is set to true
luaxml_sty.use_xml = true
--- Use XML parser for parsing of next snippets
function luaxml_sty.set_xml()
luaxml_sty.use_xml = true
end
--- Use HTML parser for parsing of next snippets
function luaxml_sty.set_html()
luaxml_sty.use_xml = false
end
--- transform XML string and print it to the output
---@param current string transformer name, empty for the default object
---@param xml_string string to be transformed
function luaxml_sty.parse_snippet(current, xml_string)
local domobject = luaxml_sty.packages.domobject
-- get the current transformer object
if current == "" then
current = luaxml_sty.current.transformation
end
local transform = luaxml_sty.transformations[current]
if not transform then
luaxml_sty.error("Cannot load transformer: " .. current)
return nil, "Cannot load transformer: " .. current
end
local dom
-- decide if we should use XML or HTML parser
if luaxml_sty.use_xml then
dom = domobject.parse(xml_string)
else
dom = domobject.html_parse(xml_string)
end
luaxml_sty.debug(dom:serialize())
local result = transform:process_dom(dom)
luaxml_sty.debug(result)
luaxml_sty.packages.transform.print_tex(result)
end
--- Transform file
---@param current string transformer name, empty for the default object
---@param filename string file to be transformed
function luaxml_sty.parse_file(current, filename)
local f = io.open(filename, "r")
if not f then
luaxml_sty.packages.transform.print_tex("\\textbf{LuaXML error}: cannot find file " .. filename)
return nil, "Cannot find file " .. filename
end
local content = f:read("*a")
f:close()
luaxml_sty.parse_snippet(current, content)
end
--- parse environment contents using Lua
---@param env_name string environment name
---@param callback_name string name which will be used in the callback registration
---@return function
-- idea from https://tex.stackexchange.com/a/574323/2891
function luaxml_sty.store_lines(env_name, callback_name)
return function(str)
luaxml_sty.debug("str", str)
local env_str = [[\end{]] .. env_name .. "}"
if string.find (str , env_str:gsub("%*", "%%*")) then
luaxml_sty.debug("end of environment")
luatexbase.remove_from_callback ( "process_input_buffer" , callback_name)
return env_str -- str
else
table.insert(luaxml_sty.verb_table, str)
end
return ""
end
end
--- require line grabbing for an environment
---@param env_name string environment name
function luaxml_sty.register_verbatim(env_name)
luaxml_sty.verb_table = {}
local callback_name = "luaxml_store_lines_".. env_name
local fn = luaxml_sty.store_lines(env_name, callback_name)
luatexbase.add_to_callback(
"process_input_buffer" , fn , callback_name)
end
--- parse content of the previous environment registered using luaxml_sty.register_verbatim()
--- and print the transformed content
---@param transformer string transformer name, empty for the default object
function luaxml_sty.print_verbatim(transformer)
luaxml_sty.parse_snippet(transformer, table.concat(luaxml_sty.verb_table, "\n"))
end
return luaxml_sty