Skip to content

Commit 627b31a

Browse files
committed
Update
1 parent 5c0bce6 commit 627b31a

File tree

1 file changed

+10
-128
lines changed

1 file changed

+10
-128
lines changed

images/exporter-texlive/templates/template.tex

Lines changed: 10 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@
4141
\usepackage{xcolor}
4242
\usepackage{titlesec} % 标题样式
4343
\usepackage{fancyhdr} % 页眉页脚
44-
\setlength{\headheight}{10pt}
45-
\usepackage{bookmark} % 增强型书签
44+
\setlength{\headheight}{7pt}
4645
\usepackage{etoolbox} % 编程逻辑
4746
\usepackage{metalogox}
4847
\usepackage{tikz}
@@ -128,124 +127,6 @@
128127
\begin{luacode*}
129128
require("lualibs")
130129

131-
local page_map_cache = {}
132-
133-
-- 解码 PDF 字符串 (UTF-16BE 或 PDFDocEncoding)
134-
function decode_pdf_string(s)
135-
if type(s) ~= "string" then s = tostring(s) end
136-
if s:byte(1) == 254 and s:byte(2) == 255 then
137-
-- UTF-16BE
138-
local out = {}
139-
for i = 3, #s, 2 do
140-
local b1, b2 = s:byte(i, i+1)
141-
if not b2 then break end
142-
local code = b1 * 256 + b2
143-
if code < 0x80 then
144-
table.insert(out, string.char(code))
145-
elseif code < 0x800 then
146-
table.insert(out, string.char(0xc0 + math.floor(code / 64), 0x80 + (code % 64)))
147-
else
148-
table.insert(out, string.char(0xe0 + math.floor(code / 4096), 0x80 + (math.floor(code / 64) % 64), 0x80 + (code % 64)))
149-
end
150-
end
151-
return table.concat(out)
152-
else
153-
-- 简单处理 PDFDocEncoding (大部分情况同 UTF-8)
154-
return s
155-
end
156-
end
157-
158-
-- 获取页面索引 (1-based)
159-
function get_page_index(doc, page_obj)
160-
if not page_map_cache[doc] then
161-
page_map_cache[doc] = {}
162-
local pages = pdfe.pagestotable(doc)
163-
for i, p in ipairs(pages) do
164-
page_map_cache[doc][p] = i
165-
end
166-
end
167-
return page_map_cache[doc][page_obj]
168-
end
169-
170-
-- 解析 Destination 为页码
171-
function resolve_destination(doc, dest)
172-
if not dest then return nil end
173-
if type(dest) == "string" then
174-
local catalog = doc.Catalog
175-
local d = nil
176-
if catalog.Dests then d = catalog.Dests[dest] end
177-
if not d and catalog.Names and catalog.Names.Dests then
178-
-- Names 树查找稍微复杂,尝试递归或直接访问
179-
-- 这里尝试一种通用的查找
180-
local function find_in_tree(node, key)
181-
if not node then return nil end
182-
local names = node.Names
183-
if names then
184-
for i = 1, #names, 2 do
185-
if tostring(names[i]) == key then return names[i+1] end
186-
end
187-
end
188-
local kids = node.Kids
189-
if kids then
190-
for i = 1, #kids do
191-
local res = find_in_tree(kids[i], key)
192-
if res then return res end
193-
end
194-
end
195-
return nil
196-
end
197-
d = find_in_tree(catalog.Names.Dests, dest)
198-
end
199-
if d then return resolve_destination(doc, d) end
200-
return nil
201-
end
202-
-- Array 形式: [page_ref, /Fit...]
203-
if type(dest) == "table" or type(dest) == "userdata" then
204-
local page_obj = dest[1]
205-
return get_page_index(doc, page_obj)
206-
end
207-
return nil
208-
end
209-
210-
-- 清理调试日志
211-
function extract_pdf_bookmarks(file_path, base_level, link_prefix)
212-
local doc = pdfe.open(file_path)
213-
if not doc then return end
214-
215-
local catalog = doc.Catalog
216-
local outlines = catalog.Outlines
217-
if not outlines or not outlines.First then
218-
pdfe.close(doc)
219-
return
220-
end
221-
222-
local function traverse(outline, level)
223-
local current = outline.First
224-
while current do
225-
local dest = current.Dest
226-
if not dest and current.A and current.A.S == "GoTo" then
227-
dest = current.A.D
228-
end
229-
230-
local page = resolve_destination(doc, dest)
231-
if page then
232-
local title = decode_pdf_string(current.Title)
233-
local open = (current.Count or 0) >= 0 and "true" or "false"
234-
tex.print(string.format("\\bookmark[level=%d, dest={%s.%d}, open=%s]{%s}",
235-
level + base_level, link_prefix, page, open, title))
236-
end
237-
238-
if current.First then
239-
traverse(current, level + 1)
240-
end
241-
current = current.Next
242-
end
243-
end
244-
245-
traverse(outlines, 0)
246-
pdfe.close(doc)
247-
end
248-
249130
function process_book_structure()
250131
-- 1. 读取文件
251132
local f = io.open("toc.json", "rb")
@@ -303,21 +184,22 @@
303184

304185
for i, chapter in ipairs(_G.book_content) do
305186
tex.print("\\chapter{" .. (chapter.title or "Chapter") .. "}")
187+
-- 兼容 sections 字段名
306188
local sections = chapter.sections or chapter.content
307189
if sections then
308190
for j, section in ipairs(sections) do
191+
-- 兼容 path 字段名
309192
local file_path = section.path or section.file
193+
local sec_title = section.title or "Section"
194+
195+
-- 检查文件路径是否为空
310196
if file_path and file_path ~= "" then
311-
local link_prefix = "pdfidx_" .. i .. "_" .. j
312-
-- 插入 PDF,带 link 锚点
197+
-- 这里如果不转义路径中的特殊字符可能会有问题,但在 Windows 路径通常斜杠处理要注意
198+
-- 最好在 Python 端把路径都转为正斜杠 /
313199
local options = "pages=-, width=\\paperwidth, height=\\paperheight, " ..
314200
"pagecommand={\\thispagestyle{fancy}}, " ..
315-
"link=true, linkname=" .. link_prefix
201+
"addtotoc={1, section, 1, {" .. sec_title .. "}, sec:" .. i .. "-" .. j .. "}"
316202
tex.print("\\includepdf[" .. options .. "]{" .. file_path .. "}")
317-
318-
-- 提取并插入该 PDF 的书签
319-
-- base_level 为 1 表示映射为 \section
320-
extract_pdf_bookmarks(file_path, 1, link_prefix)
321203
end
322204
end
323205
end
@@ -412,4 +294,4 @@
412294
\end{center}
413295
\vspace*{\fill}
414296

415-
\end{document}
297+
\end{document}

0 commit comments

Comments
 (0)