math-inc.lua /size: 2759 b    last modification: 2021-10-28 13:50
1if not modules then modules = { } end modules ['back-inc'] = {
2    version   = 1.001,
3    comment   = "companion to back-exp.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- This is an experiment. If it's really useful then I'll make a more efficient
10-- local export facility.
11
12local tonumber, next = tonumber, next
13local utfbyte, utfchar, utfsplit = utf.byte, utf.char, utf.split
14local match, gsub = string.match, string.gsub
15local nspaces = string.nspaces
16local concat = table.concat
17local xmltext = xml.text
18local undent = buffers.undent
19
20local f_entity = string.formatters["&x%X;"]
21local f_blob   = string.formatters['<?xml version="2.0"?>\n\n<!-- formula %i -->\n\n%s']
22
23local report_tags = logs.reporter("structure","tags")
24
25local all  = nil
26local back = nil
27
28local function unmath(s)
29    local t = utfsplit(s)
30    for i=1,#t do
31        local ti = t[i]
32        local bi = utfbyte(ti)
33        if bi > 0xFFFF then
34            local ch = back[bi]
35            t[i] = ch and utfchar(ch) or f_entity(bi)
36        end
37    end
38    s = concat(t)
39    return s
40end
41
42local function beautify(s)
43    local b = match(s,"^( *)<m:math")
44    local e = match(s,"( *)</m:math>%s*$")
45    if b and e then
46        b = #b
47        e = #e
48        if e > b then
49            s = undent(nspaces[e-b] .. s)
50        elseif e < b then
51            s = undent((gsub(s,"^( *)",nspaces[b-e])))
52        end
53    end
54    return s
55end
56
57local function getblob(n)
58    if all == nil then
59        local name = file.nameonly(tex.jobname)
60        local full = name .. "-export/" .. name .. "-raw.xml"
61        if lfs.isfile(full) then
62            all  = { }
63            back = { }
64            local root  = xml.load(full)
65            for c in xml.collected(root,"formulacontent") do
66                local index = tonumber(c.at.n)
67                local data  = beautify(xmltext(c,"math") or "")
68                if index and data then
69                    all[index] = f_blob(index,data)
70                else
71                    report_tags("no formula content id")
72                end
73            end
74            local it = mathematics.alphabets.regular.it
75            for k, v in next, it.digits    do back[v] = k end
76            for k, v in next, it.ucletters do back[v] = k end
77            for k, v in next, it.lcletters do back[v] = k end
78        else
79            all = false
80        end
81    end
82    if all == false then
83        return ""
84    end
85    return unmath(all[n] or "")
86end
87
88interfaces.implement {
89    name      = "xmlformulatobuffer",
90    arguments = { "integer", "string" },
91    actions   = function(n,target)
92        buffers.assign(target,getblob(n))
93    end
94}
95