由于个人的笔记资料大多是用latex编写的,经过编译得到pdf。但是pdf并不方便在线浏览访问,也不能被搜索引擎识别
为了更方便浏览,考虑将文档转换为html共享。首先找到的latex2html
这个项目,经过一番折腾,无果,于是考虑退而求其次,能否将pdf转换为html,一番搜索后找到了pdf2htmlEX
这个项目,它可以近乎无损地将pdf文件转换为html
项目地址: pdf2htmlEX
实际上项目有提供Linux版本的Release,奈何在服务器上跑并没有本地舒服。今天找到了Windows下的Release,就先从Windows讲起吧
虽然很早就知道了这个项目,但是它没有Windows的Release。由于懒得编译,而且还不会交叉编译,于是只能放弃。今天经过搜索发现已经有人编译好了Windows的版本
pdf2htmlEX Windows Version-RubyPdf Software Download Center
比较可惜的是它最新的Release只到0.14.6
,而此时项目已经更新到了0.18
。不过好在实际用起来没有什么太大差别,估计是因为我的文档比较简单吧
下载解压后得到一个文件夹,里面的的内容重要的是一个可执行文件pdf2htmlEX.exe
和一个文件夹data
。简单的方法就是在命令行执行
cmd./pdf2htmlEX.exe xxx.pdf
其中xxx.pdf
是需要转换的pdf,随后就可以在相同文件夹下得到xxx.html
。data
文件夹是主题,可以自定义,留待下文再说
项目提供了0.18.8
的Release v0.18.8.rc1
由于我用的是Ubuntu,选择下载 pdf2htmlEX-0.18.8.rc1-master-20200630-Ubuntu-bionic-x86_64.deb
shellwget https://github.com/pdf2htmlEX/pdf2htmlEX/releases/download/v0.18.8.rc1/pdf2htmlEX-0.18.8.rc1-master-20200630-Ubuntu-bionic-x86_64.deb
然后使用apt安装
shellsudo apt install ./pdf2htmlEX-0.18.8.rc1-master-20200630-Ubuntu-bionic-x86_64.deb
在使用时直接输入命令就可以了
shellpdf2htmlEX xxx.pdf
就可以在当前目录下生成xxx.html
另外需要说明的是,用该方式安装的主题目录位于
shell/usr/local/share/pdf2htmlEX
我用到的命令行参数有两个
shellpdf2htmlEX --dest-dir dddd xxx.pdf
用于将转换后的xxx.html
放到dddd
目录下
shellpdf2htmlEX --dpi 300 xxx.pdf
可以设置图片的dpi为300,默认的是144,比较模糊
总体有一个配置文件manifest
,它是一个类似于html结构的文件
html"""
<!DOCTYPE html>
<!-- Created by pdf2htmlEX (https://github.com/coolwanglu/pdf2htmlex) -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8"/>
<meta name="generator" content="pdf2htmlEX"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
"""
@base.min.css
# fancy CSS styles - Optional
@fancy.min.css
# PDF specific CSS styles - Do not modify
$css
@topbar.css
"""
<script>
try{
pdf2htmlEX.defaultViewer = new pdf2htmlEX.Viewer({});
}catch(e){}
</script>
"""
#TEST_IGNORE_END
"""
<title></title>
</head>
<body>
"""
"""
<div id="sidebar" class="opened">
"""
# container of outlines
"""
<div id="outline">
"""
$outline
"""
</div>
</div>
"""
"""
<div id="page-container">
"""
"""
<div id="topbar">
<button id="sidebar-toggle" class="top-btn">Outline</button>
<div id="scale">
<button id="zoom-in" class="top-btn">+</button>
<button id="zoom-out" class="top-btn">-</button>
<button id="auto-zoom" class="top-btn">auto</button>
</div>
</div>
"""
$pages
"""
</div>
"""
"""
<div class="loading-indicator">
"""
@pdf2htmlEX-64x64.png
"""
</div>
"""
@topbar.js
</body>
</html>
"""
猜测大概工作过程是进行字符串替换,其中由三个双引号包裹起来的内容将会被直接插入生成的html中
""" ... """
由@
开头的是文件,文件的内容将会按照类型加入。若是js脚本,会加上<script>
标签放入,若是css
,则会以css的形式加入,若是图片,则会以Base64
编码后放入。最后生成一个相当大的html
文件,不依赖于别的文件,可以直接在浏览器打开
这些东西是允许自由发挥的,像我就给他加了一个顶栏,加入了<div id="topbar">
标签,topbar.css
样式,和topbar.js
脚本,与正平常的网站开发没有什么太大区别
而由$
开头的是pdf2html由pdf文件转换得到的结果。$pages
是转换出的页面,$css
是转换出的css样式,这个是无法进行修改的
但是它转换出来依然是html,这就意味着我们可以用js脚本通过dom
去操作它。生成的html大概是这样的一个结构
html<head>
...
</head>
<body>
<div id="sidebar">
...
</div>
<div id="page-container">
<div id="..." class="pf w0 h0" ...>
...
</div>
...
</div>
</body>
sidebar
是它的目录展示,如果加上classopened
,则会显示,若没有则会关闭,并且打开关闭的动画非常丝滑...(咳)
不过非常离奇的是不管在page-container
外面写什么东西,甚至给它套层壳,都会导致sidebar
无法展示,非常见鬼。我也只能就把顶栏写在page-container
里面
操作sidebar
和page-container
可以通过id
实现
jsconst sidebar = document.getElementById('sidebar');
var container = document.getElementById('page-container');
文档的页面(就是pdf的一页一页)有一个共同的类名pf w0 h0
,w0
控制的是它的宽度,h0
控制的是它的高度。理论上应该用w0
和h0
控制宽高然而实际测试并不能修改成功非常蛋疼,因而选择获取pf
操作,不管那俩
jsvar pf=document.getElementsByClassName('pf');
for(var i=0;i<pf.length;i++){
pf[i] ... ;
}
值得欣慰的是w0
和h0
的宽高是直接写死在css里的,推测应该是根据pdf的大小确定的
另外我还自己写了一个缩放功能,写的时候需要注意以下几点
pf
类上添加transform: scale()
属性pf
包起来整体添加缩放属性,这会使所有pf
都不显示内容pf
的margin
属性,因为没有办法直接修改它的宽高,缩放会引起页面重叠page-container
的top
属性设为一定的负值,以抵消pf
的margin
属性引起的上部空白html部分已经在前文的manifest
展示过,下面是topbar.css
js#topbar{
display: flex;
justify-content: space-between;
align-items: center;
background-color: #ffffff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
height: 60px;
/* 悬浮置顶 */
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000
}
#sidebar{
margin-top: 60px;
}
#page-container{
margin-top: 60px;
}
.top-btn{
display: inline-block;
padding: 0 20px;
height: 60px;
line-height: 60px;
color: #333;
font-size: 16px;
cursor: pointer;
transition: all .3s;
border: 0;
background-color: #ffffff;
transition: all .3s;
}
.top-btn:hover{
background-color: #f5f5f5;
}
接下来是topbar.js
js// Get the button element
const sidebar_button = document.getElementById('sidebar-toggle');
// Get the sidebar element
const sidebar = document.getElementById('sidebar');
var container = document.getElementById('page-container');
//检查是否有打开的侧边栏
//获取w0的宽度
//获取h0的高度
var w0=document.getElementsByClassName('w0');
var h0=document.getElementsByClassName('h0');
var w0_width=parseFloat(getComputedStyle(w0[0]).width);
var h0_height=parseFloat(getComputedStyle(h0[0]).height);
var pf=document.getElementsByClassName('pf');
var margin=parseFloat(getComputedStyle(pf[0]).margin);
var stat=false;
if (sidebar.classList.contains('opened')) {
// Remove the "opened" class from the sidebar
stat=true;
}
var scale=1;
// Add event listener to the button
sidebar_button.addEventListener('click', function() {
// Add the "opened" class to the sidebar
if(stat){
sidebar.classList.remove('opened');
stat=false;
}
else
{
sidebar.classList.add('opened');
stat=true;
}
});
zoom_in_button=document.getElementById('zoom-in');
// 按下时给所有'pf'类添加‘transform’属性
zoom_in_button.addEventListener('click',function(){
ratio=container.scrollTop/container.scrollHeight;
scale+=0.1;
var pf=document.getElementsByClassName('pf');
for(var i=0;i<pf.length;i++){
pf[i].style.transform='scale('+scale+')';
pf[i].style.margin=margin+h0_height*(scale-1)+'px auto';
}
container.style.top=min(0,-h0_height*(scale-1)/2)+'px';
container.scrollTo(0,ratio*container.scrollHeight);
});
zoom_out_button=document.getElementById('zoom-out');
// 按下时给所有'pf'类添加‘transform’属性
zoom_out_button.addEventListener('click',function(){
ratio=container.scrollTop/container.scrollHeight;
scale-=0.1;
var pf=document.getElementsByClassName('pf');
for(var i=0;i<pf.length;i++){
pf[i].style.transform='scale('+scale+')';
pf[i].style.margin=margin+h0_height*(scale-1)+'px auto';
}
container.style.top=min(0,-h0_height*(scale-1)/2)+'px';
container.scrollTo(0,ratio*container.scrollHeight);
});
var auto_zoom_button=document.getElementById('auto-zoom');
auto_zoom_button.addEventListener('click',function(){
ratio=container.scrollTop/container.scrollHeight;
//获取page-container的宽度
var page_container=document.getElementById('page-container');
var page_container_width=parseFloat(getComputedStyle(page_container).width);
scale=page_container_width/w0_width-0.1;
var pf=document.getElementsByClassName('pf');
for(var i=0;i<pf.length;i++){
pf[i].style.transform='scale('+scale+')';
pf[i].style.margin=margin+h0_height*(scale-1)+'px auto';
}
container.style.top=min(0,-h0_height*(scale-1)/2)+'px';
container.scrollTo(0,ratio*container.scrollHeight);
});
function min(a,b){
if(a>b)
return b;
else
return a;
}
这一个缩放可真是写死人了(╯‵□′)╯︵┻━┻
已经用它将我的所有pdf文档都转换成了html,现在存放在 https://神里绫华的狗.top(不要在意这个名字,咳)
只能感叹pdf2htmlEX是真的强的,肉眼完全看不出来转换前后的差别。更多的信息请参考项目的wiki
https://github.com/pdf2htmlEX/pdf2htmlEX/wiki
完结撒花 ★,°:.☆( ̄▽ ̄)/$:.°★
本文作者:GBwater
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!