使用wkhtmltopdf转换Doxygen HTML为PDF时遇空白及JS错误
解决Doxygen HTML转PDF(wkhtmltopdf)空白问题
问题场景
使用Doxygen 1.9.4生成HTML格式文档,通过wkhtmltopdf 0.12.6(带patched qt)转换为PDF时,执行以下命令:
wkhtmltopdf --debug-javascript --enable-local-file-access *.html output.pdf
PDF成功生成但内容完全空白,同时出现警告:
Loading pages (1/6) Warning: file:///C:/Users/Downloads/Mik/html/jquery.js:2 jQuery.Deferred exception: 'null' is not an object Warning: undefined:0 TypeError: 'null' is not an object Counting pages (2/6) Resolving links (4/6) Loading headers and footers (5/6) Printing pages (6/6) Done
涉及的jQuery代码片段(Doxygen生成的标准文件):
S.extend({ Deferred: function(e) { var o = [ ["notify", "progress", S.Callbacks("memory"), S.Callbacks("memory"), 2], ["resolve", "done", S.Callbacks("once memory"), S.Callbacks("once memory"), 0, "resolved"], ["reject", "fail", S.Callbacks("once memory"), S.Callbacks("once memory"), 1, "rejected"] ], i = "pending", a = { state: function() { return i }, always: function() { return s.done(arguments).fail(arguments), this }, "catch": function(e) { return a.then(null, e) }, pipe: function() { var i = arguments; return S.Deferred(function(r) { S.each(o, function(e, t) { var n = m(i[t[4]]) && i[t[4]]; s[t[1]](function() { var e = n && n.apply(this, arguments); e && m(e.promise) ? e.promise().progress(r.notify).done(r.resolve).fail(r.reject) : r[t[0] + "With"](this, n ? [e] : arguments) }) }), i = null }).promise() }, then: function(t, n, r) { var u = 0; function l(i, o, a, s) { return function() { var n = this, r = arguments, e = function() { var e, t; if (!(i < u)) { if ((e = a.apply(n, r)) === o.promise()) throw new TypeError("Thenable self-resolution"); t = e && ("object" == typeof e || "function" == typeof e) && e.then, m(t) ? s ? t.call(e, l(u, o, R, s), l(u, o, M, s)) : (u++, t.call(e, l(u, o, R, s), l(u, o, M, s), l(u, o, R, o.notifyWith))) : (a !== R && (n = void 0, r = [e]), (s || o.resolveWith)(n, r)) } }, t = s ? e : function() { try { e() } catch (e) { S.Deferred.exceptionHook && S.Deferred.exceptionHook(e, t.stackTrace), u <= i + 1 && (a !== M && (n = void 0, r = [e]), o.rejectWith(n, r)) } }; i ? t() : (S.Deferred.getStackHook && (t.stackTrace = S.Deferred.getStackHook()), C.setTimeout(t)) } } return S.Deferred(function(e) { o[0][3].add(l(0, e, m(r) ? r : R, e.notifyWith)), o[1][3].add(l(0, e, m(t) ? t : R)), o[2][3].add(l(0, e, m(n) ? n : M)) }).promise() }, promise: function(e) { return null != e ? S.extend(e, a) : a } }, s = {}; return S.each(o, function(e, t) { var n = t[2], r = t[5]; a[t[1]] = n.add, r && n.add(function() { i = r }, o[3 - e][2].disable, o[3 - e][3].disable, o[0][2].lock, o[0][3].lock), n.add(t[3].fire), s[t[0]] = function() { return s[t[0] + "With"](this === s ? void 0 : this, arguments), this }, s[t[0] + "With"] = n.fireWith }), a.promise(s), e && e.call(s, s), s }, when: function(e) { var n = arguments.length, t = n, r = Array(t), i = s.call(arguments), o = S.Deferred(), a = function(t) { return function(e) { r[t] = this, i[t] = 1 < arguments.length ? s.call(arguments) : e, --n || o.resolveWith(r, i) } }; if (n <= 1 && (I(e, o.done(a(t)).resolve, o.reject, !n), "pending" === o.state() || m(i[t] && i[t].then))) return o.then(); while (t--) I(i[t], a(t), o.reject); return o.promise() } }); var W = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; S.Deferred.exceptionHook = function(e, t) { C.console && C.console.warn && e && W.test(e.name) && C.console.warn("jQuery.Deferred exception: " + e.message, e.stack, t) }, S.readyException = function(e) { C.setTimeout(function() { throw e }) }; var F = S.Deferred();
解决方案
方案1:禁用JavaScript渲染
wkhtmltopdf对Doxygen自带的旧版jQuery的Deferred语法兼容存在问题,直接禁用JS即可绕开错误,修改命令为:
wkhtmltopdf --disable-javascript --enable-local-file-access *.html output.pdf
Doxygen生成的HTML核心内容无需JS即可正常展示,禁用后不会影响文档的可读性和布局。
方案2:修改Doxygen配置生成纯静态HTML
在Doxygen配置文件中添加以下设置,重新生成HTML文档:
GENERATE_JAVADOCS = NO GENERATE_HTMLHELP = NO SEARCHENGINE = NO DISABLE_INDEX = YES
此配置会生成完全依赖CSS布局的静态HTML,无任何JS代码,转PDF时不会触发JS执行错误。
方案3:替换兼容版本的jQuery
找到Doxygen生成目录中的jquery.js文件,替换为wkhtmltopdf兼容的jQuery版本(如3.5.1)。替换后重新执行原转换命令,但需注意新版本jQuery可能与Doxygen的HTML结构存在样式兼容问题,此方法优先级低于前两种。
内容的提问来源于stack exchange,提问作者win.h
相关产品推荐
相关产品推荐

