deadline拯救者:定制Typora主题,论文一键排版

前言

自从用了Typora和Markdown,写各种实验报告、随笔、博客都方便快速了许多。然而当我想要(wang xiang)直接用Typora导出各种课程论文时,却发现效果不尽如人意。主要有这么几点:

  • 已有的各种英文主题对中文支持不佳,默认字体单调,不够美观;
  • 标题缺少自动编号,文章结构不清晰;
  • 看到的页宽和导出为pdf的页宽不一致;
  • ……

用来发表/投稿的论文自然是要使用

。但是对于格式要求较为宽松的课程论文之类,Markdown+css也足矣。于是我在度过了一个学期的各种deadline之后,找时间写了这样一个简单的主题,希望可以让我在下个学期的期末可以花费更少的时间在essay的排版上。

要说明的是,这个主题主要是方便最后导出为PDF的排版。我并不是在这个主题下生产学术垃圾写作——毕竟这个主题对于一个Markdown编辑器仍然有些粗糙。下面是效果图:

效果图

特点

  1. 各级标题选取合适字体,更加美观
  2. 标题自动编号,又有了不必打开Word的理由
  3. 图表下方自动编号,专业严谨
  4. 表格采用三线表,简洁清晰
  5. A4页面设定,编辑器内所见即所得
  6. 提供.md格式的封面模板,写作->排版->导出PDF全过程一处进行

下载

后面的内容主要是讲:

我,一个css入门选手,如何摸爬滚打拼凑出了这个仍然很简陋的主题。

如果你对这个过程不感兴趣的话,可以直接下载安装试用。

  • Github项目地址
  • 下载页面

如何在Typora使用自定义主题

在Typora上方工具栏点击“帮助”选项卡-Custom Themes。

或者点击此处查看帮助文档页面。

不想看英文/太长不看:

  1. 打开Typora偏好设置。(Ctrl +,)
  2. 外观-主题-打开主题文件夹
  3. 对于不同的需求,有不同的操作:
    1. 自己编写/改编主题:新建一个css文件/复制现有的css并重命名,自行修改内容
    2. 安装主题:粘贴一个已有的主题css文件到此处

4. 重启Typora,选取你的主题


从这里开始,我会一步一步介绍我写这样一个主题的过程。主要会包括这样几部分内容:

  1. 各级标题/图表 自动编号
  2. 表格的三线表格式
  3. 封面的模板和页面布局

各级标题字体

这里对各级标题的大小、选取哪个字体并没有作深入的研究。我只是从某个课程老师给出的还算好看的推荐格式里截取了关于标题的部分。(只给到四级标题,我认为再往下分没有太大意义,可以直接分段/加粗来表达论点)如果你有更喜欢的格式,可以自己修改。

这里我们遇到了第一个小问题,汉字的字号并不能直接应用于font-size属性。我的做法是通过查表,得到对应的磅数,即pt单位的大小。对于具体的换算关系,感兴趣的可以深入研究。

格式对照表

给出这部分的css:

设定标题字体css

#write {
   font-family:宋体;
   font-size:10.5pt;
}
h1,h2,h3,h4,h5,h6 {
 font-weight:bold;
}
/* 标题属性 */
h1 {
 text-align:center;
 font-size:16pt;
}
h2 {
 font-family:仿宋;
 text-align:center;
 font-size:14pt;
}
h3 {
 font-family:黑体;
 font-size:10.5pt;
}
h4 {
 text-align:center;
 font-family:楷体;
 font-size:10.5pt;
}

标题自动编号

给标题加上编号可以使整个文章更清晰,但是手动添加的话十分繁琐。但是Markdown本身并没有自动编号的语法。我们通过css的counter来实现。首先可以参考Typora关于自动编号的官方文档。这个文档里给出了示例的css代码,但是仅仅限于显示阿拉伯数字。要显示诸如“一、(二)”这样中文的编号,可以给counter传入一个参数:

counter(xxx,cjk-ideographic)

其实后面的参数可以取大部分list-style-type,更多的样式参考MDN:list-style-type

这里,我选取的编号格式如下:

目录和侧边栏自动编号

如果直接修改使用上面的样式,会发现只有编辑区的标题有自动编号。但是我们也希望Typora左侧边的侧边栏大纲,以及使用[toc]插入的目录中中也能显示自动编号。所以我们可以在样式中分别添加相应的选择器。

目录中对应的标题可以像这样选择:.md-toc-content .md-toc-h1

大纲中的标题可以这样选择:.sidebar-content .outline-h1。但是直接这样选取会导致编号和标题分为两行,不是很美观,所以我们再往下选取.outline-label

最后得到这部分的样式是这样的:

自动编号css

/* 编辑器内标题 */
#write h1 {
    counter-reset: h2;
}#write h2 {
    counter-reset: h3;
}#write h3 {
    counter-reset: h4;
}#write h4 {
    counter-reset: h5;
} #write h2:before {
    counter-increment: h2;
    content: counter(h2, cjk-ideographic) "、";
}
#write h3:before {
    counter-increment: h3;
    content: "(" counter(h3, cjk-ideographic) ")";
}
#write h4:before {
    counter-increment: h4;
    content: counter(h4, decimal) ". ";
}
/* 目录标题 */
.md-toc-content .md-toc-h1 {
    counter-reset: toc-h2;
}.md-toc-content .md-toc-h2 {
    counter-reset: toc-h3;
}.md-toc-content .md-toc-h3 {
    counter-reset: toc-h4;
}.md-toc-content .md-toc-h4 {
    counter-reset: toc-h5;
} .md-toc-content .md-toc-h2:before {
    counter-increment: toc-h2;
    content: counter(toc-h2, cjk-ideographic) "、";
}
.md-toc-content .md-toc-h3:before {
    counter-increment: toc-h3;
    content: "(" counter(toc-h3, cjk-ideographic) ")";
}
.md-toc-content .md-toc-h4:before {
    counter-increment: toc-h4;
    content: counter(toc-h4, decimal) ". ";
}
/* 大纲标题 */
.sidebar-content .outline-h1 {
    counter-reset: outline-h2;
}.sidebar-content .outline-h2 {
    counter-reset: outline-h3;
}.sidebar-content .outline-h3 {
    counter-reset: outline-h4;
}.sidebar-content .outline-h4 {
    counter-reset: outline-h5;
} .sidebar-content .outline-h2 .outline-label:before {
    counter-increment: outline-h2;
    content: counter(outline-h2, cjk-ideographic) "、";
}
.sidebar-content .outline-h3 .outline-label:before {
    counter-increment: outline-h3;
    content: "(" counter(outline-h3, cjk-ideographic) ")";
}
.sidebar-content .outline-h4 .outline-label:before {
    counter-increment: outline-h4;
    content: counter(outline-h4, decimal) ". ";
}

图表自动编号

这里按理也比较简单,在前面的基础上根据图片和表格标签加几个counter,然后也用伪元素显示出来就好了。但是这里有一些坑。

第一个坑:如果用md-image,md-table类选择器的话,由于最后导出PDF的时候这些属性都会被清除掉,会导致这些样式不能展现在最终的文件中。所以我们要用更加基础的选择器。但是这样又遇到了第二个坑。

第二个坑:表格的话不能直接用table,因为这样显示的伪元素会挤在表格里面;但是用figure标签选择就可以,因为编辑器中的表格是一个figure标签的子元素。

但是图片如果用img标签添加伪元素,会发现伪元素对img标签无效,具体可以查阅MDN有关伪元素的文档。而且也没有特殊的父元素可以替代。这个如果不用js的话我目前还没有很好的办法解决,找到过一个比较老的在img中添加content的方法,可是在现在版本的Typora中的Chromium内核中好像不适用了。

目前的版本是这样的:

/* 表格自动编号 */
#write figure:after{
 counter-increment: tableHead;
 content: "表" counter(tableHead) " ";
 text-align:center;
 width:100%;
 display:inline-block;
}
/* 图片自动编号,导出PDF时暂时无法显示 */
#write .md-image:after{
 counter-increment: imgHead;
 content: "图" counter(imgHead) " ";
 text-align:center;
 width:100%;
 display:inline-block;
}

页面尺寸

导出为pdf格式时默认为A4大小,我们给编辑区域#write元素添加一些属性使其和A4相符:

   max-width: 21cm; /*A4标准宽度*/
   padding:3.18cm 2.54cm; /*左右/上下 边距,参考了word的默认边距*/
   border:1px solid #CCC; /* 添加一个淡灰色的边框 */

这样在编辑器中看到的内容和最终导出的效果就相差无几了。

三线表

论文中常用的三线表格式,大概有这么几点要求(我没有找到确切的格式要求,这里自己试了一下觉得还行):

  • 无竖线,上下两侧边线1.5pt;列标题和数据分割线0.75pt;
  • 数据内容宋体,7.875pt;列标题黑体,9pt;

css如下,比较简单:

/* 三线表 */
#write table{
 border-top: 1.5pt solid;
 border-bottom: 1.5pt solid;
 font-family:宋体;
 font-size:7.875pt;
    text-align:center;
}#write thead{
 border-bottom: 0.75pt solid;
 font-family:黑体;
 font-size:9pt;
}

封面

这个直接用html+内联css写一下,嵌入markdown文件就好了。使用的时候将对应内容修改一下。

学校名称和校徽自行修改为对应的图片,一般在学校官网的视觉系统页面可以找到,最好是SVG格式,保持拉伸之后的清晰度。根据尺寸不同可能还要自己调整一下间隔,如添加或删除几个换行。

由于设置了page-break-after:always;打印时封面之后会添加一个分页,不用 担心正文内容挤在第一页。

<div class="cover" style="page-break-after:always;font-family:仿宋;width:100%;height:100%;border:none;margin: 0 auto;text-align:center;">
    <div style="width:80%;;margin: 0 auto;height:0;padding-bottom:25%;">
        <img src="校名.svg" alt="校名" style="width:100%;"/>
    </div>
    </br></br></br></br>
    <div style="width:40%;margin: 0 auto;height:0;padding-bottom:40%;">
        <img src="校标.svg" alt="校徽" style="width:100%;"/>
 </div>
    </br></br>
    <p style="text-align:center;font-size:24pt;margin: 0 auto">《课程名称》</p>
    <p style="text-align:center;font-size:24pt;margin: 0 auto">论文类型 </p>
    </br>
    </br>
    <table style="border:none;text-align:center;width:80%;font-family:仿宋;margin: 0 auto;">
    <tbody style="font-family:仿宋;font-size:16pt;">
     <tr style="font-weight:bold;"> 
      <td style="width:30%;text-align:justify;">题    目</td>
      <td style="width:5%">:</td> 
      <td style="font-weight:normal;border-bottom: 2px solid;text-align:center;"> 论文题目</td>     </tr>
     <tr style="font-weight:bold;"> 
      <td style="width:30%;text-align:justify;">上课时间</td>
      <td style="width:5%">:</td> 
      <td style="font-weight:normal;border-bottom: 2px solid;text-align:center;"> 上课时间</td>     </tr>
     <tr style="font-weight:bold;"> 
      <td style="width:30%;text-align:justify;">授课教师</td>
      <td style="width:5%">:</td> 
      <td style="font-weight:normal;border-bottom: 2px solid;text-align:center;">教师姓名 </td>     </tr>
     <tr style="font-weight:bold;"> 
      <td style="width:30%;text-align:justify;">姓    名</td>
      <td style="width:5%">:</td> 
      <td style="font-weight:normal;border-bottom: 2px solid;text-align:center;"> 你的名字</td>     </tr>
     <tr style="font-weight:bold;"> 
      <td style="width:30%;text-align:justify;">学    号</td>
      <td style="width:5%">:</td> 
      <td style="font-weight:normal;border-bottom: 2px solid;text-align:center;">你的学号 </td>     </tr>
     <tr style="font-weight:bold;"> 
      <td style="width:30%;text-align:justify;">组    别</td>
      <td style="width:5%">:</td> 
      <td style="font-weight:normal;border-bottom: 2px solid;text-align:center;"> 你的组别</td>     </tr>
     <tr style="font-weight:bold;"> 
      <td style="width:30%;text-align:justify;">日    期</td>
      <td style="width:5%">:</td> 
      <td style="font-weight:normal;border-bottom: 2px solid;text-align:center;">完成日期 </td>     </tr>
    </tbody>              
    </table>
</div>

效果图如下:

完整css(不包括封面)

/* 正文区基本属性 */
#write {
   font-family:宋体;
   font-size:10.5pt;
   max-width: 21cm; /*A4标准宽度*/
   padding:2.54cm 3.18cm ; /*上下/左右 边距,参考了word的默认边距*/
   border:1px solid #CCC; /* 添加一个淡灰色的边框 */
   counter-reset: tableHead 0 imgHead 0;
}
h1,h2,h3,h4,h5,h6 {
 font-weight:bold;
}
/* 标题属性 */
h1 {
 text-align:center;
 font-size:16pt;
}
h2 {
 font-family:仿宋;
 text-align:center;
 font-size:14pt;
}
h3 {
 font-family:黑体;
 font-size:10.5pt;
}
h4 {
 text-align:center;
 font-family:楷体;
 font-size:10.5pt;
}
/* 目录标题属性 */
.md-toc-h2 {
 font-family:仿宋;
}
.md-toc-h3 {
 font-family:黑体;
}
.md-toc-h4 {
 font-family:楷体;
}
/* 三线表 */
#write table{
 border-top: 1.5pt solid;
 border-bottom: 1.5pt solid;
 font-family:宋体;
 font-size:7.875pt;
    text-align:center;
}

#write thead{
 border-bottom: 0.75pt solid;
 font-family:黑体;
 font-size:9pt;
}
/* 以下开始为自动编号 */
/* 表格 */
#write figure:after{
 counter-increment: tableHead;
 content: "表" counter(tableHead) " ";
 text-align:center;
 width:100%;
 display:inline-block;
}
/* 图片,导出PDF时暂时无法显示 */
#write .md-image:after{
 counter-increment: imgHead;
 content: "图" counter(imgHead) " ";
 
 text-align:center;
 width:100%;
 display:inline-block;
}

/* 编辑器内标题 */
#write h1 {
    counter-reset: h2;
}#write h2 {
    counter-reset: h3;
}#write h3 {
    counter-reset: h4;
}#write h4 {
    counter-reset: h5;
} #write h2:before {
    counter-increment: h2;
    content: counter(h2, cjk-ideographic) "、";
}
#write h3:before {
    counter-increment: h3;
    content: "(" counter(h3, cjk-ideographic) ")";
}
#write h4:before {
    counter-increment: h4;
    content: counter(h4, decimal) ". ";
}
/* 目录标题 */
.md-toc-content .md-toc-h1 {
    counter-reset: toc-h2;
}.md-toc-content .md-toc-h2 {
    counter-reset: toc-h3;
}.md-toc-content .md-toc-h3 {
    counter-reset: toc-h4;
}.md-toc-content .md-toc-h4 {
    counter-reset: toc-h5;
} .md-toc-content .md-toc-h2:before {
    counter-increment: toc-h2;
    content: counter(toc-h2, cjk-ideographic) "、";
}
.md-toc-content .md-toc-h3:before {
    counter-increment: toc-h3;
    content: "(" counter(toc-h3, cjk-ideographic) ")";
}
.md-toc-content .md-toc-h4:before {
    counter-increment: toc-h4;
    content: counter(toc-h4, decimal) ". ";
}
/* 大纲标题 */
.sidebar-content .outline-h1 {
    counter-reset: outline-h2;
}.sidebar-content .outline-h2 {
    counter-reset: outline-h3;
}.sidebar-content .outline-h3 {
    counter-reset: outline-h4;
}.sidebar-content .outline-h4 {
    counter-reset: outline-h5;
} .sidebar-content .outline-h2 .outline-label:before {
    counter-increment: outline-h2;
    content: counter(outline-h2, cjk-ideographic) "、";
}
.sidebar-content .outline-h3 .outline-label:before {
    counter-increment: outline-h3;
    content: "(" counter(outline-h3, cjk-ideographic) ")";
}
.sidebar-content .outline-h4 .outline-label:before {
    counter-increment: outline-h4;
    content: counter(outline-h4, decimal) ". ";
}

/* override the default style for focused headings */
#write>h3.md-focus:before,
#write>h4.md-focus:before,
#write>h5.md-focus:before,
#write>h6.md-focus:before,
h3.md-focus:before,
h4.md-focus:before,
h5.md-focus:before,
h6.md-focus:before {
    color: inherit;
    border: inherit;
    border-radius: inherit;
    position: inherit;
    left:initial;
    float: none;
    top:initial;
    font-size: inherit;
    padding-left: inherit;
    padding-right: inherit;
    vertical-align: inherit;
    font-weight: inherit;
    line-height: inherit;
}

学术论文格式的尝试

对于像样的论文,和上面主要有这样几点区别:

  • 标题自动编号改为阿拉伯数字+"."连接,例如1.1, 1.2.3等
  • 标题字体更统一
  • 内容分为两栏
  • 摘要和表格跨栏显示

这些用css都不难实现。但是有一个致命的问题是,使用column-count:2实现的分栏只是将全部内容分栏,这样导出PDF时会导致前半部分内容全部在各个页面的左边,即第一页的左右两部分并不连续。而我们想要的阅读效果只是在导出时同一个页面内分栏。这个问题除了手动添加分页符我也没有找到更好的解决办法,所以这个方案的尝试宣告失败。

参考资料

有关各种效果的实现

  • http://support.typora.io/Auto-Numbering/
  • https://blog.csdn/zgmzyr/article/details/6074371
  • https://blog.csdn/qq_33159059/article/details/87910522
  • https://wwwblogs/liuxianan/p/css-counters.html
  • http://zihua.li/2013/12/keep-height-relevant-to-width-using-css/

其他参考文档

  • https://developer.mozilla/zh-CN/docs/Web/Guide/CSS/Counters
  • https://developer.mozilla/zh-CN/docs/Web/CSS/CSS_Counter_Styles
  • https://developer.mozilla/zh-CN/docs/Web/CSS/display
  • https://www.w3school/cssref/css_units.asp
  • https://www.w3school/cssref/pr_list-style-type.asp

下载

我知道你懒得往上翻了,这里再给一次下载地址:

项目地址​github 下载页面​github

本文其他地址

我的博客 我的公众号

更多推荐

typora导出word指定样式_deadline拯救者:定制Typora主题,论文一键排版