Calibre-web 通过油猴插件修改字体和code元素换行

查看 36|回复 1
作者:hx66947218   
Calibre web本身是不支持修改字体的,除非修改里面的epub相关方法来实现。不过油猴上有个epubjsgood的脚本,可以修改部分epub的样式。本文就通过该脚本,实现修改字体
前提:
[color=]平台为Ubuntu;平台为Ubuntu;平台为Ubuntu
因安卓平台字体没法配置,能力有限,没有修改过,WIN平台页没尝试过,正常应该也支持
步骤:
1、Ubuntu安装你需要的字体
参考https://blog.csdn.net/qq_37955704/article/details/117901454
此处略过,网上很多资料
2、安装油猴插件,或者暴力猴,然后安装epubjsgood脚本,脚本地址:
https://greasyfork.org/zh-CN/scripts/416793-epubjsgood
3、具体修改位置说明:
[JavaScript] 纯文本查看 复制代码// ==UserScript==
// @name         epubjsgood
// @namespace    http://tampermonkey.net/
// @version      0.34
// @description  改善calibre-web版epubjs阅读器的使用,记住字体放大程度、背景颜色;显示进度和章节
// @AuThor       You
// @match        http://*:48083/*
// @grant   GM_getValue
// @grant   GM_setValue
// ==/UserScript==
// @license      MIT
(function () {
    'use strict';
    var that = reader.book;
    var rdt = reader.rendition;
    var chapter="";
    var flag=false;
    var navheight=0;
    //reader.rendition.themes.fontSize('1.2em');
    /*GM_addStyle (`
    #divider.show {
      display: block;
    }
    `);*/
    //document.getElementsByClassName("show")[0].style.visibility="hidden";//在这里是找不到的,因为还没有被设置,会报错
    //document.getElementById("divider").id="divider2"//直接把该容易的id改掉,就不会有中间的竖线
    //document.getElementById("divider").style.visibility="hidden"
    var divshow = $(".md-content");
    //divshow.text("");// 清空数据
    divshow.append('字体大小:缩小放大   
');
    divshow.append('字体:楷体黑体宋体华文楷体华文隶书-->汉仪仿宋简汉仪仿宋简粗汉仪仿宋繁体方正仿宋幼圆方正俊黑楷书粗体幼圆粗方正字迹瘦银体霞鹜新致宋
');
    divshow.append('背景:淡黄橄榄    分隔:显示隐藏
');
    //divshow.append('背景淡黄橄榄
');
    var panelshow = $("#panels");
    //divshow.text("");// 清空数据
    panelshow.append('loc');
    var style = document.createElement("style");
    style.type = "text/css";
    var text = document.createTextNode("modal .label{  font-weight: bold;  width: 150px;  border: none;}.modal span{  padding: 0 10px;  display: inline-block;  width: 50px;}.modal span:nth-child(2){  border-right: 1px solid #ccc;}.modal span:nth-child(5){  border-right: 1px solid #ccc;}.modal .setting{  cursor: pointer;}.setting:hover{  color: #FCC;}.modal .smaller{  font-size: 100%;}.modal .larger{  font-size: 100%;}.modal p{  border-bottom: 1px solid #ccc;  -webkit-touch-callout: none;  -webkit-user-select: none;  -khtml-user-select: none;  -moz-user-select: none;  -ms-user-select: none;  user-select: none;}");
    style.appendChild(text);
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(style);
/* var prevBtn =document.createElement("BUTTON");
    var prevBtntext=document.createTextNode("CLICK ME");
    prevBtn.appendChild(prevBtntext);
    var body = document.getElementsByTagName("body")[0]
    var firstChild = document.body.firstChild
    document.body.insertBefore(prevBtn,firstChild);*/
    //定义获取章节的函数
    function getchapter(locationCfi) {
       var tmpchapter=chapter;
       try {
           //let locationCfi = reader.rendition.currentLocation().start.cfi;
           let spineItem = reader.book.spine.get(locationCfi);
           let navItem = reader.book.navigation.get(spineItem.href);
           if (navItem.label!="") {
               tmpchapter=navItem.label.replace(/[\r\n]/g,"");//去除回车,章节的主题
           }
           else {
               tmpchapter=chapter.replace(/[\r\n]/g,"");//去除回车,最初的主题,一般是作者
           }
       } catch(error) {
           console.log("获取不到章节名称:"+error.message);
       }
       return tmpchapter;
    }
    //每两秒更新一次章节和进度
    //setInterval(function(){
    function updateprogess(){
            var part1=""
            var part2="";
            try {
                part1=getchapter(reader.rendition.currentLocation().start.cfi);//获取章节名称
            } catch(error) {
                console.log("cfi获取失败",error.message)
            }
            if (navheight==0) {
                //reader.SidebarController.show()
                //$("#tocView").scrollTop(10000000)
                //navheight=$("#tocView").scrollTop()
                //$("#tocView").scrollTop(0)
                //console.log(navheight)
                //reader.SidebarController.hide()
            } //else
/*            {
                $("#tocView").scrollTop(parseInt(navheight*0.55))
                console.log("定位测试")
            }*/
            try {
                var progress=0
                if (flag) {
                    //实时进度版,速度慢
                    var lct = reader.book.locations
                    var currentLocation = reader.rendition.currentLocation();
                    progress = Math.floor(((lct.percentageFromCfi(currentLocation.start.cfi)).toFixed(5)) * 10000) / 100;
                }
                else {
                    //简化版,速度快,适应性差
                    var lct2=reader.rendition.currentLocation().start.index
                    var total2=0
                      var i=0
                      for (i = 0; i 100) {progress=100}
                    part2='[' + progress + '%]';
                    //console.log(navheight*progress)
            } catch(error) {
                console.log("进度计算失败:"+error.message);
            }
            $("#chapter-title")[0].innerText = part1+part2;
      }
    //每两秒更新一次章节和进度
    //setInterval(function(){
    //     updateprogess();
    // }, 2000);
//**********************
    reader.rendition.hooks.content.register(function(contents, view) {
      updateprogess();
    })
    $(document).ready(function () {
         function locatemychapter() {
            //$("#tocView").scrollTop(parseInt(800+navheight*parseFloat(reader.rendition.location.start.percentage)))
             //console.log(reader.rendition.location.start.percentage);
           /*
           以下为定位到当前位置,与进度配合使用,感觉不如直接按要求定位方便
           let locationCfi = reader.rendition.currentLocation().start.cfi;
           let spineItem = reader.book.spine.get(locationCfi);
                   let lcttoc=reader.book.navigation.tocByHref[spineItem.href]
           let lctclass="#toc-"+reader.book.navigation.toc[lcttoc].id
           let mainContainer = $('#tocView');
           let scrollToContainer = mainContainer.find(lctclass);
           mainContainer.animate({scrollTop: scrollToContainer.offset().top -100- mainContainer.offset().top + mainContainer.scrollTop()}, 500);
           scrollToContainer[0].children[0].style.color="red"*/
           //*************改写为按指定位置定位
           var target=prompt()
                   let lcttoc=reader.book.navigation.toc[target]
           let lctclass="#toc-"+reader.book.navigation.toc[target].id
           let mainContainer = $('#tocView');
           let scrollToContainer = mainContainer.find(lctclass);
           mainContainer.animate({scrollTop: scrollToContainer.offset().top -100- mainContainer.offset().top + mainContainer.scrollTop()}, 500);
           scrollToContainer[0].children[0].click()
           //alert(lctclass)
         }
        function setFontSize(amount) {
            reader.rendition.themes.fontSize(amount);
            //reader.rendition.themes.font('KaiTi_GB2312');
            //console.log("RENDITION_THEMES:"+reader.rendition.themes);
            //reader.rendition.themes.default({ "p": { "font-family": "KaiTi !important"}});
             document.getElementById("labelfont").innerHTML=amount
         }
         function setFonttype(fonttype){
            var fontname=fonttype+" !important;";
            //var fontname="\"font-family\":"+fonttype+" !important;";
            //alert(fontname);
           // reader.rendition.themes.default({ div: { "text-wrap": "break--word !important;"}});
            reader.rendition.themes.default({ "body": { "font-family": fontname}});
            reader.rendition.themes.default({ "body": { "word-wrap": "break-word !important;"}});
            reader.rendition.themes.default({ "body": { "white-space": "pre-line;"}});
           //reader.rendition.themes.default({ "body": {fontname}});
            reader.rendition.themes.default({ "p": { "font-family": fontname}});
            reader.rendition.themes.default({ "p": { "word-wrap": "break-word !important;"}});
            reader.rendition.themes.default({ "pre": { "white-space": "pre-line !important;"}});
            reader.rendition.themes.default({ "p": { "white-space": "pre-line;"}});
            reader.rendition.themes.default({ "pre": { "word-wrap": "break-word;"}});
           //reader.rendition.themes.default({ "p": {fontname}});
            reader.rendition.themes.default({ "pre": { "font-family": fontname}});
            //reader.rendition.themes.default({ "h2": { "font-family": fontname}});
            reader.rendition.themes.default({ "code": { "font-family": fontname}});
         }
         function changeFontSize(amount) {
            var p_value=GM_getValue("myfontsize", "2.0");
            var valuenew=Math.round((parseFloat(p_value)+amount)*100)/100
            if (valuenew=4.8) {valuenew=4.8}
            reader.rendition.themes.fontSize(valuenew+"em");
           document.getElementById("labelfont").innerHTML=valuenew+"em"
           GM_setValue("myfontsize", valuenew)
         }
         function changeBackgroundColor(color) {
            //reader.book.settings.styles['backgroundColor'] =color;
            //reader.book.settings.styles['color'] = color;
            $('#main').css('background-color', color);
            //reader.book.render.applyStyles();
           GM_setValue("mycolor", color)
         }
         function changelinestate(linestate) {
           document.getElementById("divider").style.visibility=linestate
           GM_setValue("mylinestate", linestate)
         }
         $('span.smaller').click(function() { changeFontSize(-0.1); });
         $('span.larger').click(function() { changeFontSize(0.1); });
         $('span.black').click(function() { changeBackgroundColor("#F6F4EC"); });
         $('span.white').click(function() { changeBackgroundColor("#E1E6D7"); });
         $('span.showline').click(function() { changelinestate(""); });
         $('span.hideline').click(function() { changelinestate("hidden"); });
         //字体绑定事件
         $('span.KaiTi').click(function() { setFonttype("KaiTi"); });
         $('span.SimHei').click(function() { setFonttype("SimHei"); });
         $('span.SimSun').click(function() { setFonttype("SimSun"); });
         $('span.STKaiti').click(function() { setFonttype("STKaiti"); });
         $('span.STLiti').click(function() { setFonttype("STLiti"); });
         $('span.YouYuan').click(function() { setFonttype("YouYuan"); });
         $('span.FZJunHeiS').click(function() { setFonttype("FZJunHeiS"); });
         $('span.FZFengYaSongS-GB').click(function() { setFonttype("FZFengYaSongS\-GB"); });
         $('span.zktqkt').click(function() { setFonttype("zktqkt"); });
         $('span.FZZJ-SYTJW').click(function() { setFonttype("FZZJ\-SYTJW"); });
         $('span.LXGW').click(function() { setFonttype("\'LXGW Neo ZhiSong Demo 2751\'"); });
         $('span.FZFS').click(function() { setFonttype("FZFangSong\-Z02"); });
         $('span.HYFSF').click(function() { setFonttype("HYFangSongF"); });
         $('span.HYCFS').click(function() { setFonttype("HYCuFangSongJ"); });
         $('span.HYFSJ').click(function() { setFonttype("HYFangSongJ"); });
         $('span.CloudYuanCuGBK').click(function() { setFonttype("CloudYuanCuGBK"); });
         $('span.AaBoruokaishuBold').click(function() { setFonttype("AaBoruokaishuBold"); });
        $('a.icon-edit').click(function() { locatemychapter(); });//绑定定位位置
        var valuenow=GM_getValue("myfontsize", "1.6");
        setFontSize(valuenow+"em");
        //changeFontSize(GM_getValue("myfontsize", "1em"));
        changeBackgroundColor(GM_getValue("mycolor", "#ffffff"));
        changelinestate(GM_getValue("mylinestate", ""));
        //左侧菜单栏的panel会挡住一部分滚动条,用这条语句设置后不会挡
        document.getElementById("panels").style.width="280px"
        document.getElementById("tocView").style.height="95%"
        //reader.rendition.themes.default({ "body": { "font-family": "KaiTi !important"}});
        //reader.rendition.themes.default({ "h3": { "font-family": "KaiTi !important"}});
            that.ready.then(() => {
                try {
                chapter=$("#chapter-title")[0].innerText;//获取默认章节要在此处理
                } catch(error) {console.log("获取不到chapter:"+error.message);}
                console.log("初始化定位开始,千章可能要10分钟");
                return that.locations.generate()
            }).then(result => {
                console.log("初始化定位完成");
                //$("#tocView ul").children("li").each(function(){navheight = navheight + $(this).outerHeight(true);});
                //console.log(navheight);
                flag=true
        })
    });
})();
3.1 其中主要新增了一个设置字体的方法setFonttype方法
[Asm] 纯文本查看 复制代码         function setFonttype(fonttype){
            var fontname=fonttype+" !important;";
            //var fontname="\"font-family\":"+fonttype+" !important;";
            //alert(fontname);
           // reader.rendition.themes.default({ div: { "text-wrap": "break--word !important;"}});
            reader.rendition.themes.default({ "body": { "font-family": fontname}});
            reader.rendition.themes.default({ "body": { "word-wrap": "break-word !important;"}});
            reader.rendition.themes.default({ "body": { "white-space": "pre-line;"}});
           //reader.rendition.themes.default({ "body": {fontname}});
            reader.rendition.themes.default({ "p": { "font-family": fontname}});
            reader.rendition.themes.default({ "p": { "word-wrap": "break-word !important;"}});
            reader.rendition.themes.default({ "pre": { "white-space": "pre-line !important;"}});
            reader.rendition.themes.default({ "p": { "white-space": "pre-line;"}});
            reader.rendition.themes.default({ "pre": { "word-wrap": "break-word;"}});
           //reader.rendition.themes.default({ "p": {fontname}});
            reader.rendition.themes.default({ "pre": { "font-family": fontname}});
            //reader.rendition.themes.default({ "h2": { "font-family": fontname}});
            reader.rendition.themes.default({ "code": { "font-family": fontname}});
         }
主要是用reader.rendition.themes.default以及js的!important;强制改变iframe中的字体已经换行样式
部分元素可以打开
3.2 函数调用时机
在页面ready的时候给相关元素添加click事件,其中相关元素在上面样式中定义,一般页面右上角齿轮可以点开,
[JavaScript] 纯文本查看 复制代码         $('span.smaller').click(function() { changeFontSize(-0.1); });
         $('span.larger').click(function() { changeFontSize(0.1); });
         $('span.black').click(function() { changeBackgroundColor("#F6F4EC"); });
         $('span.white').click(function() { changeBackgroundColor("#E1E6D7"); });
         $('span.showline').click(function() { changelinestate(""); });
         $('span.hideline').click(function() { changelinestate("hidden"); });
         //字体绑定事件
         $('span.KaiTi').click(function() { setFonttype("KaiTi"); });
         $('span.SimHei').click(function() { setFonttype("SimHei"); });
         $('span.SimSun').click(function() { setFonttype("SimSun"); });
         $('span.STKaiti').click(function() { setFonttype("STKaiti"); });
         $('span.STLiti').click(function() { setFonttype("STLiti"); });
         $('span.YouYuan').click(function() { setFonttype("YouYuan"); });
         $('span.FZJunHeiS').click(function() { setFonttype("FZJunHeiS"); });
         $('span.FZFengYaSongS-GB').click(function() { setFonttype("FZFengYaSongS\-GB"); });
         $('span.zktqkt').click(function() { setFonttype("zktqkt"); });
         $('span.FZZJ-SYTJW').click(function() { setFonttype("FZZJ\-SYTJW"); });
         $('span.LXGW').click(function() { setFonttype("\'LXGW Neo ZhiSong Demo 2751\'"); });
         $('span.FZFS').click(function() { setFonttype("FZFangSong\-Z02"); });
         $('span.HYFSF').click(function() { setFonttype("HYFangSongF"); });
         $('span.HYCFS').click(function() { setFonttype("HYCuFangSongJ"); });
         $('span.HYFSJ').click(function() { setFonttype("HYFangSongJ"); });
         $('span.CloudYuanCuGBK').click(function() { setFonttype("CloudYuanCuGBK"); });
         $('span.AaBoruokaishuBold').click(function() { setFonttype("AaBoruokaishuBold"); });
font-family可以在terminal中用fc-list|grep  
[color=][安装的字体名称]
可以看到,配置上即可
3.3 页面元素展示添加
[JavaScript] 纯文本查看 复制代码    var divshow = $(".md-content");
    //divshow.text("");// 清空数据
    divshow.append('字体大小:缩小放大   
');
    divshow.append('字体:楷体黑体宋体华文楷体华文隶书-->汉仪仿宋简汉仪仿宋简粗汉仪仿宋繁体方正仿宋幼圆方正俊黑楷书粗体幼圆粗方正字迹瘦银体霞鹜新致宋
');
    divshow.append('背景:淡黄橄榄    分隔:显示隐藏
');
    //divshow.append('背景淡黄橄榄
');
    var panelshow = $("#panels");
    //divshow.text("");// 清空数据
    panelshow.append('loc');
通过上述3个步骤,重启web就可以在齿轮中设置字体,以及code的换行(不用可以注释了),经测试,大部分文件是可以做到更换字体的,但是少部分可能是样式写在p标签内,无法失效更换字体
具体有感兴趣的小伙伴如果配置过程有问题,可以楼下留言,我如果能解决,很乐意帮助

字体, 仿宋

TW烟雨   
过来学习一下
您需要登录后才可以回帖 登录 | 立即注册

返回顶部