Good good study, day day up

aleung的学习笔记, aleung的idea

HTML Presentation Framework

| Presentation

最近要做一个分享,需要做个有趣一些的 slides。工作上的 slides 都是用 PowerPoints 来做的,但 ppt 放网上分享不方便,而且也不 cool,因此琢磨着弄个什么来玩玩。开始打算想用 markdown 来写,一方面是习惯了,另外也够简便。几年前就曾试过用 markdown 写一个简单的 slides

上网搜索一圈,发现这种打着 “HTML presentation framework” 名号的工具还真多,近些年来 HTML5、CSS、JavaScript 的广泛应用,这些基于 HTML 的演示可以做得很炫,让人耳目一新,例如这个 50 Years of the Rolling StonesMass of Planets (要允许网页使用摄像头)。

比较了一下,感觉 reveal.js 不错,也很受欢迎。后来又发现另外一个后起之秀 bespoke.js,影响力不够 reveal.js 大,但它的插件式设计更胜一筹。对了,这些工具基本上都是用 JavaScript/Node.js 等一套工具链的,前端相关的技术 js 独霸天下了。

先试了一下 bespoke.js。看到 reveal.js 能使用 Leap Motion Controller 来手势控制,演示起来会比较出彩,正好同事有一个 leap motion,可以借来玩,但是却找不到 bespoke.js 支持 leap motion 的插件。查了一下,原来 leap 有 JavaScript API,在浏览器里面能够通过事件监听获得双手各个手指的位置和手势动作的信息,API 暴露出来的已经是处理后的双手模型了,应用用起来相当方便。于是就简单的 port 了一个 bespoke-leapmotion 插件出来。但说实在的,leap motion 这东西还是中看不中用,用手势切换页面根本就不如手指头按个按键快捷和省力,手势的辨别也不够精准(这方面应用在数据处理上是可以下些功夫的)。

Bespoke.js 的 markdown 支持似乎还有些坑,总有这样那样的问题。而且在 markdown 在版面布局方面局限性也很大,做出来的 slides 显得单调了些,效果不够理想,于是又在看看直接用 HTML 来写会怎样。HTML 是足够灵活了,但是要设置排版布局又累死了,我对 HTML+CSS 也不是那么熟悉,有点想放弃用回 PowerPoint 了。

正好这个时候,发现了 slides.com 这个网站,它背后用的就是 reveal.js,但它的在线编辑器真心好用啊,鼠标拖放元素,功能简洁但又足够做出漂亮的效果了。就是它了!

但是,我还是念念不忘 leap motion —— 演示的时候可以带来新奇的效果啊。Slides.com 自然不会有这偏门的功能,但它很良心的提供了 export to reveal.js,在上面编辑好的 slides 可以放回本地的 reveal.js 里面播放,免费用户都可以享受。嗯,看起来一切都好,可是,怎么在 slides.com 里面写好的 speaker notes 导出后都丢失了呢?查看导出文件的内容,似乎是 slides.com 内部处理 speaker notes 用的机制跟 reveal.js 不一样,存放的格式也不同了。还好,只要数据都在,还是有办法的,写个程序来转换就行了。

永恒的终结

| Reading

花了几天空余时间,看完了阿西莫夫的科幻小说《永恒的终结》

在我的印象中,阿西莫夫的科幻小说是以逻辑严谨为特征的。他的好多作品都是设定在未来背景的侦探推理小说。小学时代读他的“机器人系列”,还以为机器人三大定律真的是生产机器人都需要固化的逻辑。总之,感觉他的书基本上都是烧脑之作,读起来要细细思考琢磨的。

(提示: 有关键情节透露)

在《永恒的终结》的设定中,时间的流逝是绝对的、单向的。即使在永恒时空,依然存在着时间的流逝(所谓的物理时间)。时间作用在永恒之人身上,他们依然会变老。严格的说,在整部小说的设定中,只存在一个时空,也就是一般时空。并不存在着一个独立的永恒时空,永恒时空其实是锚定在一般时空之上的一个个节点(在某些世纪上存在一个分区),永恒时空的时间跟一般时空的时间是同步的流逝的。

《永恒的终结》并没有引入其他科幻小说常用的平行时空的概念,或者说即使有平行时空,他们(永恒之人)也只能在其中一个时空上活动。永恒之人的特别之处在于他们拥有着在时间轴上穿行的能力,他们能够到达时空上的任何一个时刻(也包括空间位置,但这在故事中不是重点)。将时空中的活动想象为一盘按正常速度播放录像带,永恒之人就是能够倒退或者快进到录像带的某个时刻进行播放。无论如何,在这(唯一的)时空之中,因果率是起作用的,也就是说,这盘录像带的剧情是合乎因果情理来发展的,前一时刻的事件产生的后果会反映到后面的时刻中。永恒之人在时空之中穿梭观察,以一个旁观者的身份,他可以看到一件事情发生的前因后果。

但是,永恒之人要亲临一般时空的某个时刻进行观察,免不了会对该时刻发生的事件带来影响,因为这不像我们看录像带,超脱于录像的时空之外,前面说了时空其实始终只有一个,永恒之人进入某个时刻,也就是成为录像带场景中的一部分了。他在这个时刻的任何行动,都会在后续的时刻带来后果,也就是干扰了现实,带来了现实的变革。变革有多大,视乎影响的大小,如果恰好改变了因果链的一个关键节点,就会对后续的社会发展带来很大的影响,也就是永恒之人所做的现实变革。

虽然永恒之人可以随时进入某个时刻,做某些事情去改变现实,但他们并不能预先观察到引发的后果。因为这个一般时空是严格遵从因果律的,时空技师可以先去2481世纪看看是什么样子的,然后去2456世纪去实施现实变革计划,但是他看到的2481世纪只会是没有变革的,他没办法预先看到变革后的2481世纪,因为他还没有改变2456世纪发生的事件,无因就无果。当时空技师在2456世纪干预了某些事件,带来了连锁反应的后果,再去看2481世纪,这时他看到的就跟之前看到的2481世纪不一样了,之前的2481世纪已经不存在——只存在在他的记忆里——现实已经被改写。这就是为什么技师爱上了482世纪的一个女人,但当现实变革后,他即使再回到482世纪也无法找回他的爱人——也许她不存在了,也许在新的现实里她从来就没有爱过他。小说冲击了读者的一个观念:在具体的某一个时刻,发生过的事情永远不会改变。在这里,时间只是一个一维坐标系,事件并不是固化在上面的,就像可以将一件物品从空间一个位置上挪走,同样可以在时间上改变某个时刻发生的事件。

因为永恒之人并无法预先观测到现实变革的后果,他们只能依靠先进的计算机阵列和经验丰富的计算师去预测某个方案能够带来怎样的变化。不知道他们是怎样为世界的运转建模的,还有超凡的计算能力去预估一个扰动在逐渐发散的因果链上带来的后果。不过,跟蝴蝶效应之类的理论不同,在小说中设定为现实的演进是存在惯性的,一个扰动并不会带来无限发散的后续影响,而是经过一段时间后回归到跟没有扰动发生过一样的演进状态。所以,一个现实变革可能会影响几个世纪乃至上百个世纪的演进,但不会带来无穷的影响。

如果这种影响只是单向的:永恒之人可以进入某个时刻,给这个时间带来影响,那么一切还是很完美,因果链始终是开放无穷伸展的,不会成为闭环。但是小说其实还是要回到时空旅行的经典因果悖论:循环因果中去。

其实时间的因果悖论在永恒时空之中也存在:一个永恒之人是不是能够返回到前几天,去改变全时理事会的一次会议讨论?但小说将永恒时空设定为非连续的时空(至少一个世纪才有一个分区),绕开了这个问题,因为小说要指向一个更加大的悖论。

(注意:以下关键剧透)

小说将永恒时空的建立,或者说时空旅行的技术的产生,设定为是永恒之人将未来(27世纪)才发现的数学原理带回24世纪而创造的。这样,因果链条就形成了闭环了,前事之因带来后事之果,而后事却又是前事之因(这里的前、后指的是时间轴上的坐标)。那么,一旦“后事”没有发生,“前事”又何来呢?答案还是那个:现实将被抹去,一切都没有发生过。这与现实变革其实是一样的,永恒之人实施现实变革是对某个时刻实施干预,影响它的后果而将当前现实更替为另外一个现实;而永恒时空的建立本身就是一个来自未来的干预的结果,因此永恒之人需要去实施这个干预,以保证因果链的闭合,使得当前现实得以保存。一旦这个预期的干预没有发生,从那个时刻起的现实就毁灭了,变成一个新的现实——没有发生过来自未来的干预的现实。

但是我始终没有想明白的是,假若时间旅行是可行的,这种循环因果链在逻辑上可能存在吗?它是怎样形成的?可以不存在一个第一推动者?

小说最终的三个章节的转折还是让我意料不及,用的道理是很平白的:生于忧患,死于安乐,整个人类也是如此。拥有了时空穿行能力的人类会不断的通过现实变革,将人类的发展历史局限在一个安稳的状态。但是缺失了外太空探险精神的人类就在与外星文明的竞争中落败了。

在我的个人阅读体验里,读到最后几页感觉是前面做了如此华丽的铺垫,图穷匕见的却是一个建立银河帝国的俗套的梦想,颇有失望。

阿西莫夫将毁灭永恒时空的动机解释为男女之间的爱情,也许爱情是世界上最重要的东西,唯有它才能产生改变整个时空的动力。但阿西莫夫毕竟还是写逻辑推理更擅长,写起男女感情来完全读不出味道。


豆瓣书评:http://book.douban.com/review/7495652/

Jekyll 与 Swagger UI 集成

| SoftwareDev

Swagger 是被广泛使用的用于 REST API 描述和文档化的框架。它制定了一个用于描述 REST API 的规范,提供了一组工具用于编辑 API 描述文件、生成测试客户端、生成文档等等。Swagger UI 是其中的用于生成文档的工具。

Jekyll 是深受程序员喜爱的静态网站生成工具,通常用来做 blog 站点,我们的工作团队也用它来做内部的技术文档库

在 Jekyll 里描述我们产品的 REST API,编辑排版是比较繁琐的事情,不同的 API 描述也没有统一的风格,因此考虑到引入 Swagger 来规范化 API 定义。

为此,写了一个简单的 Jekyll 插件,只要像下面例子那样在 markdown 中简单的插入 swagger tag,指定 API 描述文件,相应的 API 文档就会由 Swagger UI 生成并嵌入在页面中。

{% swagger /api/my-api.json %}

安装使用方法请参看 README。另外,Swagger UI 没有考虑到在一个页面中显示多组 API,会有些显示问题,已经提交 pull request,下个版本有望修复,暂时可以先下载我的修改版本,详见 README。

几条基础排版规则,让文档显得专业

| Blogging

虽然我不是处女座的,但在有些事情上会表现得比较处女座,例如对于文档格式,我常会跟各种细节纠缠不休,为的是看起来显得完美一些。

作为软件开发者,写文档是必备的技能,而且文档里常常会出现大量英文。这里介绍一些很基本的规则,使得文档的显得专业一些。这些规则在其他类型的文章里也是适用的。

规则

用段落,不要强制换行

在我看来,禁止使用强制换行,是没有特例的(我们不写诗歌)。在必须保留原始换行的地方,应该作为 preformatted text block(HTML 的 PRE,markdown 的 4 空格缩进段落)出现。

保持一致性

保持标点、字体等元素的一致性,整篇文档看起来清晰整齐,可读性高。

在这方面常见问题有:

中文英文标点混用

写技术文章,经常会出现中文英文(西文)混合的场景。原则应该是在中文句子中使用中文标点,西文句子中使用西文标点。至于中文句子中嵌入西文引文,那么嵌入的西文内容中应该遵循西文引文这个“亚环境”的规则,用西文标点,但用来包裹嵌入内容的引号或者括号还是属于中文句子的环境,因此用中文标点。

简体繁体中文混用
这个如果不考虑海外用户,问题也不算大,对大陆读者来说,混合简体繁体阅读起来基本上没有违和感。
全角半角混用
除了中文标点外,西文字母和数字这些字符是不应该出现全角的。
成对的符号没有对称
例如引号,是区分左引号和右引号的,一般输入法会正确识别方向,但在拷贝粘贴或者插入编辑的时候要小心方向不要弄错。

空格的使用

中文标点不需要加空格。西文标点后需要加一个空格;成对的符号,开始的要在前面加空格,结束的在后面加空格。

西文单词之间要用空格分隔,这个不容易错。但是单词与数字之间也要加空格,例如“iPhone 6”。

中文与西文混排时,中文与西文之间可能要添加空格,以保证有一定间距,具体视乎显示效果而定。有人习惯一律加空格。1 2

西文大小写不要误用

强调以下的规则似乎有点小题大做,但确实还是经常会见到这样的错误。

  • 句子首字母大写,句子内不应该用大写,除非下面的情况;
  • 有些专有名词首字母大写的,即使用在句子中间也要保留大写;
  • 全部大写的缩写,放在哪里都不能变成小写。

西文没有书名号

书名号是中文特有的。在西文中,书名用斜体表示,篇名用引号。

使用样式,不要在文字上添加格式

同样语义的文字,就应该有同样的显示效果,这也是一致性的体现。把文字变得五颜六色,再插一段超大字体,这种做法还是留在小毛孩的论坛里吧。

不要滥用强调

强调会吸引注意力,打破文档视觉结构,只应该用在真正需要的地方。满篇的强调等于没有强调。

若要突出文档架构,应该使用标题(headings)。当文章中有些整行文字需要强调时,往往是应该将它们作为小标题。

在西文中,按照强调的程度不同,一般强调用斜体,特别强调用加粗。但是,斜体只适合西文,中文不好看,在印刷中可以用楷体或者加着重号代替,不过在一般电子文档中不方便使用(在 web 上可以用 CSS 来控制),没有什么好方法,所以在中文中就没法区分一般强调和特别强调了。 3

改颜色改字体大小之类的奇淫技巧不可使用。

合理使用格式

通过合理使用语义化的格式,可以达到需要的显示效果,而不用去直接指定如何显示。HTML 和 markdown 都支持以下几种格式:

引用 (blockquote)
整段文字引用自其他地方。
Preformatted text block
保留原始格式,包括换行,空格等。
代码格式
用等宽字体(monospaced font)显示。要做得漂亮一点就是加上自动语法高亮渲染了。
定义列表 (definition list)
适用于一个名词,后面一段解释的场合,就像现在这段文字。也就是 key-value map 在文本中的体现。在HTML 里是 DL, DTDD 标签,不属于基本的 markdown 格式,有些引擎会支持。

总结

保证各种元素的一致性。关注内容的层次结构,段落或文字的语义属性,而不是显示效果。显示效果由样式来控制。


Jekyll

| Blogging

用 Jekyll 作为内部技术文档库

去年在公司的产品开发团队中推行了使用 Jekyll 静态网站生成工具来写内部技术文档,大半年下来,效果还不错。

内部技术资料的共享和维护以前一直是个问题。开始用 Office Word 正正规规的写设计文档,维护成本太高了,往往是代码已经翻天覆地变化,文档里都没有反映出来,大家不愿意更新。而且查找起来也不方便。后来推行敏捷方法,不想让文档工作那么 heavy 了,于是用 wiki 来记录。Wiki 的问题是信息非常碎片化,大家很随意的添加新页面,整个 wiki 就像一个草稿本,写得很没有系统。网状的超链接导航令读者很迷茫,不知道需要的信息入口在哪儿,有些隐藏得很深的页面没有几个人知道它们的存在。Wiki 的在线编辑体验也不是那么好。

Jekyll 是个静态网站生成工具,采用 markdown 语法来写内容,根据模板生成 HTML 页面,发布到一个 web 服务器上,就可以用浏览器在线查看内容。Jekyll 通常用来做 blog 系统,但它用来做有组织的内容发布系统也是完全胜任的。我基本上就是仿照 Jekyll 官方文档 的风格和结构来组织我们产品的内部技术文档库。

使用 Jekyll 优点首先是编写方便,markdown 是个轻量的标记语言,上手简单,语法易记,而且有不少编辑工具支持。即使没有渲染成 HTML,也是直接可以阅读的,比起奇奇怪怪还各自不同的 wiki 语法好写多了。

在模板做得好以及安装合适的插件后,生成的文档显示效果相当漂亮,格式效果也很丰富。而且,我们使用了 plantuml 插件,可以直接用文字的方式UML1,比起以前用其他工具画图,截图,再嵌入文档这种方式方便多了。

技术文档库的原始文件是文本格式,用 git 来做版本管理,不用担心大家同时编辑保存时会相互覆盖的问题,修改历史也很清晰。大家都是程序员,本来代码就是用 git 来管理的,文档也用 git 管理自然是很顺手的事情。使用 jekyll-post-revision 这个插件,能够在生成的页面上显示修改历史记录。

通过 jekyll-lunr-js-search 这个插件,能为站点提供全文搜索的能力,这也是相当方便的功能。

在 Windows 上安装 Jekyll

Jekyll 是用 Ruby 开发的,在 Linux 和 Mac OS X 上安装使用都很简单,在系统中有 Ruby 环境的前提下(Mac 是自带的,Linux 的各种发行版都会有安装包),照着官网上的介绍,几个命令就搞定了。但是,在 Windows 下就不是那么简单了(顺便再黑一下 Windows,不使用 Microsoft 技术的开发者都应该离开它)。

在 Windows 上装过几次 Jekyll,可以写点教程减少大家摸索的时间。大致参考这篇 Run Jekyll on Windows

安装 Ruby

首先需要安装 Ruby 环境。从 http://rubyinstaller.org/downloads 下载 Ruby 2.0 和 DevKit,安装 Ruby,然后将 DevKit 解压到 C:/RubyDevKit,在命令行运行下面指令完成安装。

1
2
3
cd C:\RubyDevKit
ruby dk.rb init
ruby dk.rb install

安装 Jekyll 相关的 gem

Gem 是 Ruby 的包管理工具。在命令行执行gem install可从互联网的仓库直接下载和安装需要的包。如果需要代理,需要先设置环境变量http_proxy,如不需要则忽略第一行。其中,jekyll这个 gem 是必须安装的,其他的视乎环境、配置和使用的插件,可能需要装,可能不需要装。

1
2
3
4
5
6
7
8
9
10
set http_proxy=http://my-proxy:8080

gem install jekyll

gem install kramdown
gem install pygments
gem install nokogiri
gem install coderay
gem install wdm
gem install json

如果在安装过程中出现 SSL 错误,从这里可以找到解决方法。

使用 Jekyll

Jekyll 的相关操作都是执行jekyll命令进行。后面的基本上就是看官方文档慢慢折腾了。

制作 jekyll.exe

上面的步骤还是有点繁琐。我们公司里的都是 Java 程序员,在电脑里装个 Ruby 环境也没有其他用处。为了推广使用,简化大家的操作,做一个 portable 的 Jekyll 可执行程序会更好。

制作的步骤基本上参考这篇 Building Jekyll.exe for Windows

首先要安装 OCRA。可能还需要安装 psych,bigdecimal 这些 gem。

1
gem install ocra

解开 jekyll 到一个临时目录:

1
gem unpack jekyll

修改bin/jekyll,在开头增加几个依赖声明:

1
2
3
require 'nokogiri'
require 'jekyll-watch'
require 'wdm'

生成 exe 文件:

1
ocra --add-all-core --gem-all bin/jekyll lib/jekyll/mime.types lib/site_template/**/* lib/site_template/*

做出来的 jekyll.exe 需要测试一下,看看各种命令是否都能正常。视乎配置和使用插件的不同,可能需要增加更多的依赖声明。以上只是我的环境的例子,不一定适用于所有场景。

最后,我知道大家都还是懒得衣来伸手饭来张口的,就提供一个编译好的 jekyll.exe 下载,支持 kramdown 和 coderay。但还是那句话:不一定符合你的环境。