Org To Site Tutor
Table of Contents
如果你是第一次访问这个页面,强烈建议先跳转至附录的 网站功能图示 章节,浏览一下站点的功能使用概要 :)
Emacs China 中的描述,比较散乱,这里整理一下。我尽量把所有的操作步骤纳入其中,以避免不必要的跳转。
更新日志
1. 预计更新
[ ]
本地全局搜索功能(Hurricane's 实现);[ ]
添加 RSS 、sitemap 、robots.txt
2. 过往更新
- 新增文内随笔样式,随手记录一些东西(2020-08-26 Wed 18:51)
- 新增批注样式,如右侧所示,使用方法见附录右侧批注样式(2020-07-27 Mon 11:01)
这就是批注喽,可以充分利用右侧的空间。
- 新增
user.config.js
,抽离一些配置项(微博、GitHub、Author 等)(2020-07-26 Sun 22:36)- 新增执行脚本
copy.sh
,用来在 Emacs 外部同步拷贝图片、JS、CSS 等资源文件(2020-05-29 Fri 21:04)- 新增执行脚本
update.sh
,原因详见 关于执行脚本 (2020-05-26 Tue 16:45)- 双击代码块开始复制,10s 后自动恢复行号(原来的悬浮隐藏有的体验不好)(2020-05-17 Sun 13:04)
- 激活毛玻璃风格(总看纯白色,有点腻歪了……)(2020-05-16 Sat 21:05)
- 对带行号代码块的处理(复制时隐藏行号,确保复制内容只含代码)(2020-04-17 Fri 15:04)
- 添加导航页 ,包括导航和书签 (2020-04-11 Sat 12:11)
- 调整 IDEA 页面样式(2020-04-04 Sat 02:36)
- 本地化依赖库,实现点击查看页面全屏尺寸图片(2020-04-03 Fri 21:58)
- 显示当前代码块类型(2020-04-02 Thu 15:02)
- 添加 网站功能图示 (2020-03-27 Fri 19:49)
- 录制删除当前文章的宏(2020-03-22 Sun 18:55)
- 视频闲聊这个项目 (2020-03-04 Wed 22:46)
起步
这个章节中,我们会叙述如何 让项目先运行起来 ,这才是主要的,不是吗?放心,我们会在后续章节中介绍细节。
1. 克隆项目到本地家目录
1: # 进入家目录 2: # → Windows 3: # C:\Users\<用户名>\AppData\Roaming\site 4: cd C:\Users\jack\AppData\Roaming 5: # → Gnu/linux & MacOS 6: cd ~ 7: 8: # 克隆项目到家目录 9: git clone https://github.com/loveminimal/site.git site
*2. 克隆 Emacs 配置到家目录
如果,你想直接使用自己的 Emacs 配置, 跳过这一步 即可。
如果,你想使用我的这份配置,那么,完成这一步之后,项目就可以跑起来了。
1: # 克隆 Emacs 配置到家目录 2: git clone https://github.com/loveminimal/emacs.d.git .emacs.d
注意,这是我自己在用的 Emacs 配置,你可以先使用它跑一下 Emacs ,体验一下项目效果。
2. 拷贝 Emacs 配置到你的配置中
!因为支持这个项目的配置已经单独抽离了出来 – init-site.el ,所以,可以很方便的把它拷贝到你自己的 Emacs 配置中。
另外,因为我的配置文件是用 use-package 组织管理的,如果你自己的配置不是基于它的,你就不得不安装 use-package 了,很简单,只需要贴入如下一段配置即可(并不会影响你原来的配置):
1: (unless (package-installed-p 'use-package) 2: (package-refresh-contents) 3: (package-install 'use-package)) 4: 5: (eval-when-compile 6: (require 'use-package))
只要保证上述 use-package
的安装代码,在 init-site.el
中的配置之前执行即可(你总得先安装了它,才能使用它,是吧)。
至此,所有的准备工作,都已经完成了!
启动 Emacs 后,打开 ...site/org/index.org
文件,执行 M-x preview-current-buffer-in-browser
即可看到效果。
简介
本文旨在介绍如何利用 org-publish
把 .org
文件生成为 .html
,以及如何解决静态文件(主要是图片)的缩放问题。
Emacs 是一个强大的 “编辑器” ,或者说 “操作系统” ,它具备强大的可扩展性,拥有丰富的插件, Org Mode 便是其中的佼佼者。 Org Mode 拥有优秀的文本组织方式,并且可以输出多种文本格式,如 .md
、 .txt
、 .html
等。
这个站点的生成方式其实很简单,灵感来自于多方面。感谢 org-html-themes 项目,Virgo 的生成和组织结构都借鉴了该项目。感谢 Emacs China 社区的朋友,他们提供了许多不错的建议和指导。
文件组织方式
site | |-- org # .org 文件 | |-- xxx.org | |-- assets # 其它静态文件 | |-- doctor.mp3 | |-- css # 样式文件,已配置 | |-- style.css | |-- images # 图片文件 | |-- xxx.jpg/png/gif | |-- js # 逻辑文件 | |-- darkreader.js | |-- main.js | |-- theme-rose.setup # 头文件 | |-- xxx.sh # 可选的执行脚本,如 copy.sh、update.sh | |-- public # 发布后生成的 .html 文件及静态文件 | |-- ...
建议把 site 文件夹放在家目录:
- GNU/Linux 、 Mac 是
~/
; - Windows 是
C:\Users\jack\AppData\Roaming
,jack
是当前电脑的用户名。
这样做有什么好处呢?
在 Windows 下,Emacs 的配置默认生效的目录就是 C:\Users\jack\AppData\Roaming
,该目录被称为漫游家目录。如此,将 site 文件夹也放在这个目录,就会有很多的好处,比如, .emacs.d
和 site
的相对位置是固定的,基于此你可以做一些定制化的便捷性操作(写一些操作脚本等),并且在切换到 Linux 上使用的时候,保持了操作行为的统一。
Emacs 中的配置
目前,并没有把在 Emacs 中的配置,组织成插件,比较分散,这个主题用来介绍 Virgo 站点生成所需要的配置。
在我的 emacs.d 配置中,插件主要使用 use-package 组织管理,它同样也是 spacemacs 项目所采用的的组织方式。
htmlize
该插件用来转换并打开生成的 .html
文件。
1: (use-package htmlize 2: :ensure t 3: ;; :config 4: ;; (setq htmlize-output-type 'font) 5: )
ox-html
1: (use-package ox-html 2: :config 3: (setq 4: ;; org-html-doctype "html5" 5: ;; org-export-default-language "ch" 6: user-full-name "Jack Liu")) ;; 将 "Jack Liu" 更换成你自己的的名称,网站脚注处的 Author 值
ox-publish
这个是 Emacs 中内置的输出功能,它也是 Virgo 站点生成的核心所在。为了不让大家感到困扰,我把 Virgo 没有用到的一些配置代码全部删除了,如果你想了解更多可以查看 init-orgs.el 文件。强烈建议按照默认的配置使用,等熟悉之后再自定义。
如 文件组织方式 所述,把 site
文件夹放在家目录,配置中设置 :base-directory
等时设置目录比较方便。
1: (use-package ox-publish 2: :config 3: 4: (setq org-publish-project-alist 5: '(("orgfiles" 6: ;; ; Sources and destinations for files. 7: :base-directory "~/site/org/" ;; ** 源 .org 文件放置的目录 8: :publishing-directory "~/site/public/" ;; ** 生成的站点文件放置的目录 9: ;; ; Selecting files 10: :base-extension "org" 11: :recursive t 12: ;; ; Publishing action 13: :publishing-function org-html-publish-to-html 14: 15: ;; ;;; Options for the exporters 16: 17: ;; ; Generic properties 18: :headline-levels 4 19: :section-numbers nil 20: :with-author "Jack Liu" ;; ** 站点拥有者名称 21: :with-priority t 22: :with-toc t 23: 24: ;; ; HTML specific properties 25: :html-doctype "html5" 26: 27: ;; ; Other options 28: :table-of-contents t 29: ) 30: 31: ;; static assets 32: ;; 静态文件输出设置 33: ("js" 34: :base-directory "~/site/js/" 35: :base-extension "js" 36: :publishing-directory "~/site/public/js/" 37: :recursive t 38: :publishing-function org-publish-attachment 39: ) 40: ("css" 41: :base-directory "~/site/css/" 42: :base-extension "css" 43: :publishing-directory "~/site/public/css/" 44: :recursive t 45: :publishing-function org-publish-attachment 46: ) 47: ("images" 48: :base-directory "~/site/images/" 49: :base-extension "jpg\\|gif\\|png\\|svg\\|gif" 50: :publishing-directory "~/site/public/images/" 51: :recursive t 52: :publishing-function org-publish-attachment 53: ) 54: ("assets" 55: :base-directory "~/site/assets/" 56: :base-extension "mp3" 57: :publishing-directory "~/site/public/assets/" 58: :recursive t 59: :publishing-function org-publish-attachment 60: ) 61: ("webfonts" 62: :base-directory "~/site/webfonts/" 63: :base-extension "eot\\|svg\\|ttf\\|woff\\|woff2" 64: :publishing-directory "~/site/public/webfonts/" 65: :recursive t 66: :publishing-function org-publish-attachment 67: ) 68: 69: ("website" :components ("orgfiles" "js" "css" "images" "assets" "webfonts")) 70: ("statics" :components ("js" "css" "images" "assets" "webfonts")) 71: )))
默认输出设置
Emacs 默认的 ox-publish
会输出一些默认格式,因为比较原生,我们把它禁止掉,只保留对于代码块的高亮。
1: (progn 2: "Settings of `org-export'." 3: (setq org-export-in-background t 4: ;; Hide html built-in style and script. 5: org-html-htmlize-output-type 'inline-css ;; 保留代码块高亮 6: org-html-head-include-default-style nil 7: org-html-head-include-scripts nil 8: ))
自定义函数
保存并输出页面
为了减少频繁重复性的操作,我们对默认的输出函数进行了一些封装,如下:
1: (defun save-and-publish-website() 2: "Save all buffers and publish." 3: (interactive) 4: (when (yes-or-no-p "Really save and publish current project?") 5: (save-some-buffers t) 6: (org-publish-project "website" t) 7: (message "Site published done."))) 8: 9: (defun save-and-publish-file () 10: "save current buffer and publish." 11: (interactive) 12: (save-buffer t) 13: (org-publish-current-file t)) 14: 15: (defun save-and-publish-statics () 16: "Just copy statics like js, css, and image file .etc." 17: (interactive) 18: (org-publish-project "statics" t) 19: (message "Copy statics done."))
其中:
save-and-publish-website
用来保存当前所有 buffer ,并转换输出所有文件;save-and-publish-file
用来保存当前 buffer ,并转换输出当前文件;save-and-publish-statics
只用来拷贝静态文件资源到public
文件夹。其好处在于,当你只修改了静态文件时,无需再手动地拷贝它们,或是执行save-and-publish-website
保存输入整个项目(当.org
文件很多时,速度会很慢)。
建议,绑定函数到按键,更加方便操作。如,我使用的 evil 中它们分别被绑定到 <SPC> p w
、 <SPC> p f
和 <SPC> p s
按键。
预览当前页面
1: (defun preview-current-buffer-in-browser () 2: "Open current buffer as html." 3: (interactive) 4: (let ((fileurl (concat "http://127.0.0.1:8080/" (file-name-base (buffer-name)) ".html"))) 5: (save-and-publish-file) 6: (unless (httpd-running-p) (httpd-start)) 7: (browse-url fileurl)))
注意,当前函数基于 emacs-web-server 插件,下载并配置如下:
1: (use-package simple-httpd 2: :ensure t 3: :config 4: (setq httpd-root "~/site/public")) ;; Set default server directory
如此,当执行 M-x preview-current-buffer-in-brower
时,就可以在默认浏览器中该页面了。
删除 Org 及 Html
有时候,我们会对 .org
文件进行删除操作,为了使网站也删除这个页面,就需要删除其对应的 .html
文件,然而,每次都进行这样的步骤是一件令人讨厌的事。现在,我们可以使用下面这个函数,它会删除当前 .org
文件,且同时删除其生成的 .html
文件。
1: (defun delete-org-and-html () 2: "Delete the relative html when it exists." 3: (interactive) 4: (when (yes-or-no-p "Really delete current org and the relative html?") 5: 6: (let ((fileurl (concat "~/site/public/" (file-name-base (buffer-name)) ".html"))) 7: (if (file-exists-p fileurl) 8: (delete-file fileurl)) 9: (delete-file (buffer-file-name)) 10: (kill-this-buffer) 11: (message "Delete org and the relative html done."))))
自定义宏
删除当前文章
目前,我们在 ./index.org
的列表 Table
中管理所有的文章。通过执行这个宏 mc/delete-this-post
,可以同时删除当前光标下的 .org
文件及其对应的 .html
文件。
1: (fset 'mc/delete-this-post 2: " fo pdydd")
注:这个宏依赖于 delete-org-and-html 这个函数。
宏,会让人变“懒”。
如, mc/delete-this-post
这个宏其实就是录制了一系列的操作:
<SPC> fo
,执行打开光标下的连接;<SPC> pd
,执行delete-org-and-html
函数;y
,确定执行delelte-org-and-html
函数;dd
,删除所在光标所在行,即当前文章在主页中的行。
自定义模式
以前在使用 ox-hugo 的时候,接触到了 org-hugo-auto-export-mode
这个模式,它用来实现在保存当前 buffer 的时候,自动根据当前 .org
文件内容导出相应的 .md
。
沿着这个思路,我写了一个类似的 minor mode ,用来实现在保存当前 buffer 的时候,自动导出相应的 .html
文件。如下:
1: (define-minor-mode auto-save-and-publish-file-mode 2: "Toggle auto save and publish current file." 3: :global nil 4: :lighter "" 5: (if auto-save-and-publish-file-mode 6: ;; When the mode is enabled 7: (progn 8: (add-hook 'after-save-hook #'save-and-publish-file :append :local)) 9: ;; When the mode is disabled 10: (remove-hook 'after-save-hook #'save-and-publish-file :local)))
图片
NOTE: 这个章节只是补充,可以不了解。
静态页面的图片输出一直是个让人比较烦扰的问题,在 Windows 上输出指定大小的图片比较不易,我们可以曲线实现,在 .org
文件中插入 Html 标签,如:
#+BEGIN_EXPORT html <img src="/images/xxx.jpg" width="60%" /> #+END_EXPORT
如此,便可以指定图片输出的宽高。为了方便,你可以使用 yasnippet 写一个快速插入的 snippet ,如:
# -*- mode: snippet -*- # name: insert img # key: ii # -- <img src="/images/$1" width="${2:6}0%" />
总结
总体来说,比较简单,也不需要下载多少额外的插件,充分利用 Emacs 本身拥有的功能。综上所述,我们来总结一下步骤:
git clone https://github.com/loveminimal/site.git ~/site
,即把 site 文件夹放在家目录;- 把 Emacs 中的配置 的配置添加到 Emacs 的配置文件中;
- 在 Emacs 中执行封装的 自定义函数 即可。
如此,生成的 public 文件夹中就是你的站点所需要的一切文件,把它部署到 Github 或是私人服务器即可。
附录
网站功能图示


1. 文章列表
所有文章在主页列表中管理、分类,光标移入/移出表头,用来切换其内容(文章标题)的显示/隐藏。
2. 主题切换
站点提供了亮/暗两种主题模式,所有页面点击文章标题,即可切换。


3. 目录显隐
光标移入/移出页面左侧(移动端点击页面顶部),用来切换目录的显示/隐藏。
4. 返回主页和回到顶部
右下角,包含两个功能按钮 - IDX ←
(返回主页)和 TOP ↑
(返回页面顶部,且滚动时显示当前页面滚动百分比)。
关于执行脚本
为什么会有这个脚本?我们来看这样一种场景。
小伙伴甲表示,他正在愉快地写博客,发现“无聊的 Jack”又提交更新了一些东东……
看看提交日志,完全是其个人的一些文章的更新,不用管!(嫌弃 -_||)
看看提交日志,更新了一些小功能还不错,BUT 一但拉取了更新,自己的文章就会被覆盖…… 不更新吧,这次更新的小东西好像还有那么点意思 !_!
这个执行脚本主要解决上述问题,它会保持你的文章状态,在拉取更新后自动恢复它,避免每次手动拷贝 ^_^
已经完工了 ^_^
1. 添加当前 Repo 为新的远程库
- 执行
git remote -v
,展示当前仓库已经连接的远程库; - 执行
git remote add virgo https://github.com/loveminimal/site.git
,添加该远程库; - 再次执行
git remote -v
,检查是否添加成功。
2. 在 bash 终端执行脚本
在 Unix/Linux/Mac 下,就是在终端喽,至于 Windows ,你应该在 git-bash 中执行这个脚本(真心不想写 Powershell 脚本了…)。
如果想拉取最近的更新,只需要执行:
1: # 在 site 站点目录下,执行 2: ./update.sh
放心,它会保存你的文章状态,并在拉取更新后恢复它。
右侧批注样式
其实,使用很简单,我们把要加的批注写在 <note>...</note>
中就可以了,放心,在渲染的时候已经做好了处理,如下:
1: #+BEGIN_EXPORT html 2: <note> 3: 这就是批注喽,哈哈,可以充分利用右侧的空间。 4: </note> 5: #+END_EXPORT
原理就是,在 Org Mode 中输出 HTML 片段,指定了自定义的标签 <note>
(用来后续的 DOM 操作)。在浏览器渲染的过程中,无效的标签符并不会做为普通文本绘制出来,但其内的内容却可以。
文内随笔样式
沁园春·雪