四月一号(昨天)的精彩新闻报道:
我们知道,引用其他人的东西需要注明出处,这包括论述文字也包括图片、视频等。然而互联网上的许多图片中并没有出处、作者等信息,需要手工加注。一般来讲,我们可以在图片外使用独立的文件记录下这些引用信息,不过这着实原始,而且可能使我们的图片文件夹显得混乱。这里说一种不同的方法,通过在图片中嵌入 EXIF 信息来达到记录引用来源的目的。由于 EXIF 算是个标准,而且是内嵌在原文件中,所以应该是个更好的选择。
EXIF 基础知识参见维基。
这里使用的工具软件是 exiftool,它是一个 Perl 模块,同时提供了命令行程序。Fedora 下可以用命令 yum install perl-Image-ExifTool 安装。
具体的加入原始链接的操作示例如下:
exiftool -ArtworkSource='http://bloggersalchemy.com/sopa/' stop-sopa-pipa.jpg
之后可以用下面命令查看:
exiftool -ArtworkSource stop-sopa-pipa.jpg
另外,使用
exiftool -a -u -g1 stop-sopa-pipa.jpg
可以查看完整的内嵌信息。这条命令出自 exiftool(1) 的手册页的示例部分,更多请自行 man exiftool 之后搜索 examples。
注意上面的 ArtworkSource 其实是 XMP 中的一个标签,我最初想使用 IPTC 下的 source 标签来存储原始链接。后来发现 source 的值是个长度为 0—32 的字符串(包括最后的 NULL 结束符)着实有限,它的本义也并非存储出处信息(参考指南)。另外 IPTC 算是古老陈旧了,新的 IPTCCore 规范已经使用 XMP 格式。你可能会问这些标签名字从何得知,答案是可以看 Image::ExifTool::TagNames(3pm) 的手册页
在 PDF 文档中声明许可证信息大致有两种方式。一是直接在许可证信息写在文档内(目录之前或文档末尾等位置),另一种方式则是嵌入 XMP 元数据信息。这里讲的是后面一种方式。
XMP 并不仅限于嵌入 PDF,事实上它是独立于目标媒体的标准。可以将 XMP 数据嵌入到文档、图片、音频等各种文件中。它本质上是一段 XML 文档。详情参看 wikipedia。
在 LaTeX 下使用 XMP 在最终的 PDF 文档中嵌入许可证信息,我摸索出来的最好方法是使用 hyperxmp 宏包。这个宏包会和 hyperref 宏包配合,扩展 hyperref ,支持诸如 pdfcopyright、pdflicenseurl 等选项。这些选项的内容会最终添加到 DVI/PDF 文档的元信息中。
如下是一个简单的示例:
\documentclass{article}
% A Test to use hyperxmp package to include license info into the pdf file.
% The pdf file can be produced by pdflatex/xelatex.
% The license info can be seen in
% * Evince(File--Properties) (of a new version, v3.2.1 on Fedora 16 is ok).
% See also the hyperxmp package's doc by 'texdoc hyperxmp'.
% License of this tex file:
% Copying and distribution of this file, with or without modification,
% are permitted in any medium without royalty provided the copyright
% notice and this notice are preserved. This file is offered as-is,
% without any warranty.
\title{Hyperxmp Tests}
\author{Foo Bar}
\usepackage{hyperref}
\usepackage{hyperxmp}
\hypersetup{
pdfauthor={Foo Bar},
pdfcopyright={Copyright (C) 2012 by Foo Bar.
Licensed under CC-BY-NC-SA 3.0. Some rights reserved.},
pdflicenseurl={http://creativecommons.org/licenses/by-nc-sa/3.0/},
}
\usepackage{lipsum}
\begin{document}
\maketitle
\lipsum
\end{document}
编译可以使用 pdflatex 或者 xelatex。之后可以使用 Evince 看到如图的结果。 图片是在 Fedora 16 上 Evince 3.2.1 的截图。高版本的 Adobe Reader 应该也能看到类似的效果。注意 hyperxmp 的文档中提及使用 xelatex 引擎编译时默认情况下会压缩元数据信息,可能导致其他的 PDF 阅读器无法识别元信息。不过我的测试表明 Evince 可以识别并正确处理压缩过的元信息。另外完整的测试文件可以在我的 TeXlab 仓库中得到。测试过程中发现一个有趣的现象:当删掉 pdflicenseurl 一行后, 编译得到的 PDF 文档里的许可证信息就无法在 Evince 中看到了。
另外一种方式是使用 xmpincl 宏包。它需要单独的一个 .xmp 文件,而且目前只兼容 pdflatex 引擎。所以我觉得不是很方便易用。注意到 Creative Commons 网站上提供生成 .xmp 格式的许可证文件,所以这也算是一个可行的选择。这篇博文有关于这种方式的更多介绍。
几天前,我在系统 Fedora 16 启动过程中 Plymouth 的主题气泡快要充满时,把USB接口的鼠标接了上去,发现之后在 GDM 登录界面,移动鼠标根本不会让光标移动。使用笔记本上的触摸板倒是正常。登录进入系统后,插上U盘测试,根本出不来 /dev/sdb。换其他的USB接口,依然不行。查看日志 /var/log/messages,可以看到大量类似的行(dmesg输出也有类似信息):
Feb 20 22:00:14 localhost kernel: [ 34.571048] hub 2-0:1.0: connect-debounce failed, port 2 disabled
上网 Google,看到 Launchpad 上一个 kernel bug 讨论中,不少人遇到过这个问题。其中提到的解决方案之一是重启电脑,修改 BIOS 设置里 USB Legacy Support 或类似选项为禁用,之后进入 Linux 系统,应该不会有新的上述错误信息,USB 接口可以正常使用。再次重启,在 BIOS 中重新启用 USB Legacy Support,然后进入系统,也不会再有类似错误信息。USB 接口也可以重新正常使用。我使用了这一方法,对我的情形的确有效。(然而根据讨论,有的机器上就没有作用)
当然,潜意识告诉我:在启动未就绪时热插拔不是个好主意。不过这究竟会带来什么问题,是否会导致硬件故障,我着实没有搞清楚。
JavaScript 中数组与对象定义时最后一个元素后如果跟了一个逗号,那么可能引起问题。一个简单的例子是 [2, 3].length 等于 2,而 [2, 3,].length 在 Firefox/Chrome 中仍为 2,但在 IE (旧版)中等于 3 (它会认为最后有一个元素值为 undefined)。有关这个问题,还可以参考 Dan Lee 这篇有趣的博文,以及 Drupal 的一个 Bug 报告。而我最初是在看 GitHub 上 Hotot 的一个 Pull Request 时开始注意到这个情况。
末尾逗号的写法 C/C++ 程序员应该很习惯。末尾逗号能在改变对象中元素顺序、使用代码生成数组、拷贝代码时带来方便。然而在旧的 JavaScript 实现中,这是不允许的。根据这篇博文,IE8 里已经修复了这个 "bug"。另外,ECMAScript 5 规范里已经容许了末尾逗号,目前新版本的 Firefox/Chrome 对这个标准有良好的支持。(参见这里)
值得注意的是,JSON 规范中要求不能有末尾逗号的,否则就是格式错误。JSON 不等于 JS 对象。因此,使用代码生成 JSON 格式的字符串时,采用前置逗号是更好的实践。(参考 stackoverflow 上的这个问题)
我的 connect6-ng 是在 connect6 的基础上进行的。原项目使用 SVN 做版本控制,但我更喜欢使用 Git。所以我在开始 connect6-ng 时先检出了 SVN 仓库里的最新版本然后取出其中源代码初始化了 Git 仓库,并没有继续 SVN 历史。
董渊老师建议我能把两段历史连接起来,以体现出项目的延续性。老师还帮忙使用 git-svn 在 Ubuntu 9.10 下将 connect6 项目的 SVN 历史转换到了 Git 仓库下:
mkdir connect6.git
cd connect6.git/
git-svn init http://connect6.googlecode.com/svn/ --no-metadata
git config svn.authorsfile ../authors.txt
git-svn fetch
git log
cd ..
tar -zcvf connect6.git.tgz connect6.git/
其中authors.txt的内容为:
qq280833822 = CHEN Shuang <qq280833822@gmail.com>
wanglei = WANG Lei <leopardguo25@gmail.com>
我收到 connect6.git.tgz 后在连接两段历史前,对前一段历史记录做了一些更改:使用 git filter-branch 删除了仓库里的 *.class 文件、/trunk/connect6.jar 文件,因为我觉得这些中间文件或目标文件放在仓库里意义不大。另外,我又将 trunk 目录做成了仓库的根目录,这和后面我的仓库更接近。处理后的仓库目录我命名为 connect6-shrinked/。
参考 stackoverflow 中这个问题的回答,我使用其中的第三种方法(refs/replace/) 将 SVN 仓库历史转换成的 git 历史添加在了 connect6-ng 提交历史的前面,连上了两段历史。不太详细的步骤如下:
切换到新项目 connect6-ng 的顶层目录,把 connect6-shrinked 加为一个远程仓库,命名为 history:
$ git remote add history file:///path/to/connect6-shrinked/
然后找出 connect6-ng 项目最初的提交(Initial commit)的 SHA1 值,保存到 $TAIL 变量中:
$ TAIL=$(git rev-list --topo-order master | tail -n 1)
接着找出要导入历史的旧项目的最近的一次提交,保存到 $TOP 变量中:
$ TOP=$(git rev-parse --verify history^0)
然后读取 $TAIL 这个 commit 对象的内容:
$ git cat-file commit $TAIL > TAIL_COMMIT
手工编辑 TAIL_COMMIT 这个文件,加入一行 parent $TOP(其中 $TOP 换成对应的 SHA-1 值),这使得新项目的初始提交有了旧项目的顶部作为父提交。将新的 TAIL_COMMIT 写入仓库:
$ NEW_TAIL=$(git hash-object -t commit -w TAIL_COMMIT)
最后使用 git replace:
$ git replace $TAIL $NEW_TAIL
这样就连接好了两段历史记录,可以用 git log 等查看。
要把合并后的历史 push 出去,需要在自己仓库 .git/config 文件中对应 remote 部分加一行:
push = +refs/replace/*:refs/replace/*
在合并两段历史之前已经从 connect6-ng 远程仓库 clone 了代码仓库的同学,如果不做修改,还是只能看到较新的一段历史。要想看到旧的SVN导出的历史,需要修改自己的 .git/config 里 origin 部分(或者其他指向 connect6-ng 远程仓库的 remote 分支名)添加一行:
fetch = +refs/replace/*:refs/replace/*
这样之后 git fetch 和 git pull 就可以拉取 refs/replace/ 下的后来添加的历史了。
附注:本文参考了董渊老师和我的邮件、stackoverflow 上的回答等,一并感谢。
昨天(2月1号)给网站添加了 favicon,参考了这里。其中要注意的是如果使用了子主题,那么 favicon 需要放在子主题而非父主题的根目录中。
昨天还安装了 syntaxhighlighter 插件用于代码高亮。安装很简单,就是下载解压,然后在管理界面启用插件,具体步骤可以参考前面的链接。
今天则调整了网站副标题(CSS 中 description 类)的样式,改成了个人更喜欢的斜体衬线字。另外是花了不少精力优化打印版本页面的样式,最终通过将针对打印介质的 CSS 代码写到 Suffusion 配置中的 Back-end -- Custom Includes -- Custom Styles 部分,得到了比较好的效果(可以通过打印预览查看)。目前的 CSS 代码是(顺便测试 syntaxhighlighter
):
@media print {
body {
font-family: serif;
font-size: 10pt;
background-color: white;
color: black;
}
a:link, a:visited {
background-color: transparent;
color: #520;
text-decoration: underline;
font-weight: bold;
}
h1, h2, h3 {
background-color: white;
color: black;
}
code, pre, kbd {
overflow: visible;
}
pre {
padding: 0;
font-size: 80%;
}
div.entry a:link:after, div.entry a:visited:after {
content: " (" attr(href) ") ";
font-size: 90%;
}
/* Do not display nav bar, sidebar, etc */
#nav, #sidebar-shell-1, #commentform {
display: none;
}
#wrapper {
background-color: white;
color: black;
max-width: 100%;
min-width: 100%;
width: 100%;
margin: 0;
padding: 0;
border-style: none;
}
#container, #main-col {
width: 100%;
margin: 0;
padding: 0;
}
}
另外,今天还意外地解决了固定链接被覆盖需要重设的问题。由于我在 OpenShift 上搭的博客,组件的更新需要用 git 推送。之前我发现每次 git 推送后,WordPress 的固定链接都会失效,得在管理界面的固定链接部分再次“保存更改”才行。查看了有关固定链接的介绍后我才明白,WordPress 通过写 .htaccess 规则来实现各种格式的固定链接。我 SSH 到网站网页文件目录,用 cat(1) 查看 .htaccess 文件内容,发现比起 git 仓库的版本果然多了一些内容。将相应行内容复制到 git 仓库中,重新推送,问题就不复存在了。
将 1/998001 用小数表示,会得到 000001002… 这样的序列。我是从网上看到的,更原始的出处在此。
下面是用 bc(1) 这个计算器重现的记录,其中前两行是输入,后面是输出:
scale=6000
1/998001
.0000010020030040050060070080090100110120130140150160170180190200210\
22023024025026027028029030031032033034035036037038039040041042043044\
04504604704804905005105205305405505605705805906006106206306406506606\
70680690700710720730740750760770780790800810820830840850860870880890\
90091092093094095096097098099100101102103104105106107108109110111112\
11311411511611711811912012112212312412512612712812913013113213313413\
51361371381391401411421431441451461471481491501511521531541551561571\
58159160161162163164165166167168169170171172173174175176177178179180\
18118218318418518618718818919019119219319419519619719819920020120220\
32042052062072082092102112122132142152162172182192202212222232242252\
26227228229230231232233234235236237238239240241242243244245246247248\
24925025125225325425525625725825926026126226326426526626726826927027\
12722732742752762772782792802812822832842852862872882892902912922932\
94295296297298299300301302303304305306307308309310311312313314315316\
31731831932032132232332432532632732832933033133233333433533633733833\
93403413423433443453463473483493503513523533543553563573583593603613\
62363364365366367368369370371372373374375376377378379380381382383384\
38538638738838939039139239339439539639739839940040140240340440540640\
74084094104114124134144154164174184194204214224234244254264274284294\
30431432433434435436437438439440441442443444445446447448449450451452\
45345445545645745845946046146246346446546646746846947047147247347447\
54764774784794804814824834844854864874884894904914924934944954964974\
98499500501502503504505506507508509510511512513514515516517518519520\
52152252352452552652752852953053153253353453553653753853954054154254\
35445455465475485495505515525535545555565575585595605615625635645655\
66567568569570571572573574575576577578579580581582583584585586587588\
58959059159259359459559659759859960060160260360460560660760860961061\
16126136146156166176186196206216226236246256266276286296306316326336\
34635636637638639640641642643644645646647648649650651652653654655656\
65765865966066166266366466566666766866967067167267367467567667767867\
96806816826836846856866876886896906916926936946956966976986997007017\
02703704705706707708709710711712713714715716717718719720721722723724\
72572672772872973073173273373473573673773873974074174274374474574674\
77487497507517527537547557567577587597607617627637647657667677687697\
70771772773774775776777778779780781782783784785786787788789790791792\
79379479579679779879980080180280380480580680780880981081181281381481\
58168178188198208218228238248258268278288298308318328338348358368378\
38839840841842843844845846847848849850851852853854855856857858859860\
86186286386486586686786886987087187287387487587687787887988088188288\
38848858868878888898908918928938948958968978988999009019029039049059\
06907908909910911912913914915916917918919920921922923924925926927928\
92993093193293393493593693793893994094194294394494594694794894995095\
19529539549559569579589599609619629639649659669679689699709719729739\
74975976977978979980981982983984985986987988989990991992993994995996\
99799900000100200300400500600700800901001101201301401501601701801902\
00210220230240250260270280290300310320330340350360370380390400410420\
43044045046047048049050051052053054055056057058059060061062063064065\
06606706806907007107207307407507607707807908008108208308408508608708\
80890900910920930940950960970980991001011021031041051061071081091101\
11112113114115116117118119120121122123124125126127128129130131132133\
13413513613713813914014114214314414514614714814915015115215315415515\
61571581591601611621631641651661671681691701711721731741751761771781\
79180181182183184185186187188189190191192193194195196197198199200201\
20220320420520620720820921021121221321421521621721821922022122222322\
42252262272282292302312322332342352362372382392402412422432442452462\
47248249250251252253254255256257258259260261262263264265266267268269\
27027127227327427527627727827928028128228328428528628728828929029129\
22932942952962972982993003013023033043053063073083093103113123133143\
15316317318319320321322323324325326327328329330331332333334335336337\
33833934034134234334434534634734834935035135235335435535635735835936\
03613623633643653663673683693703713723733743753763773783793803813823\
83384385386387388389390391392393394395396397398399400401402403404405\
40640740840941041141241341441541641741841942042142242342442542642742\
84294304314324334344354364374384394404414424434444454464474484494504\
51452453454455456457458459460461462463464465466467468469470471472473\
47447547647747847948048148248348448548648748848949049149249349449549\
64974984995005015025035045055065075085095105115125135145155165175185\
19520521522523524525526527528529530531532533534535536537538539540541\
54254354454554654754854955055155255355455555655755855956056156256356\
45655665675685695705715725735745755765775785795805815825835845855865\
87588589590591592593594595596597598599600601602603604605606607608609\
61061161261361461561661761861962062162262362462562662762862963063163\
26336346356366376386396406416426436446456466476486496506516526536546\
55656657658659660661662663664665666667668669670671672673674675676677\
67867968068168268368468568668768868969069169269369469569669769869970\
07017027037047057067077087097107117127137147157167177187197207217227\
23724725726727728729730731732733734735736737738739740741742743744745\
74674774874975075175275375475575675775875976076176276376476576676776\
87697707717727737747757767777787797807817827837847857867877887897907\
91792793794795796797798799800801802803804805806807808809810811812813\
81481581681781881982082182282382482582682782882983083183283383483583\
68378388398408418428438448458468478488498508518528538548558568578588\
59860861862863864865866867868869870871872873874875876877878879880881\
88288388488588688788888989089189289389489589689789889990090190290390\
49059069079089099109119129139149159169179189199209219229239249259269\
27928929930931932933934935936937938939940941942943944945946947948949\
95095195295395495595695795895996096196296396496596696796896997097197\
29739749759769779789799809819829839849859869879889899909919929939949\
95996997999000001
我用 Vim 做一些简单的处理,只保留小数点后部分,得到每三个数字一行的格式:
:%s/\\\n//g
:s/\(\d\d\d\)/\1\r/g
用下面的 Ex 命令(Vimscript) 可以验证序列的连续递增性:
let i = 1
while i < 1000
if (i - 1) != str2nr(getline(i), 10)
echo i
endif
let i = i + 1
endwhile
你会发现中间缺少且只缺少一个 998…
一般的计算器会截断小数结果。Octave 里直接 printf 格式化输出也得不到这么长的结果。如果你使用其他工具可以得到足够长的结果,不妨把方法告诉我。
CSS 是 web 设计中非常重要的一部分。CSS 也非常的强大,通过指定 media 类型,可以为不同的显示设备指定不同的显示样式。CSS2 可以识别的 media 类型中有屏幕显示(screen)、打印版本(print)、投影仪(projection) 等, 而且不止这些,参见这里。 可以期望 CSS3 会引入更多的 media 类型(比如 3D 眼镜?)。如果 media 类型是 all,则意味着 CSS 文件适合各种设备。这也是缺省设置,未指定特定 media 类型的样式规则会适用于所有设备。
可以在 HTML 文件中指定 CSS 文件适合的 media 类型:
<link href="style1.css" rel="stylesheet" media="all" type="text/css" />
<link href="print.css" rel="stylesheet" media="print" type="text/css" />
不过这样浏览器需要请求多个 CSS 文件,有人担心可能引起性能问题。 我们还有另外一种方式在一个 CSS 文件中为不同的 media 指定不同的样式规则。 例如下面的 CSS 代码使得页面字体无衬线且比较大,适合如今的电脑屏幕; 而打印版本使用 12pt 的带衬线字体,且指定白底黑字,适于打印。
@media screen {
body {
font-family: sans-serif;
font-size: 16px;
}
}
@media print {
body {
font-family: serif;
font-size: 12pt;
background-color: white;
color: black;
}
}
关于适合打印的 CSS 设计,alistapart 和 meyerweb 有不错的介绍。
CSS 指定 media 类型时还支持带逻辑运算的高级选择, 通过它可以更精细地为不同屏幕大小指定不同的样式,以更好地设计网页。 下面是一个来自 CSS-Tricks 的例子:
@media all and (max-width: 699px) and (min-width: 520px), (min-width: 1151px) {
body {
background: #ccc;
}
}
其中 and 是逻辑与,逗号代表逻辑或。此外 not 也可以使用。更多的介绍参见 CSS-Tricks,事实上我还没有用到这个高级功能。
CSS 标准中有关于分页媒质特有属性和选择器 (selector) 的介绍, 然而我试图使用 :first 选择器时发现在 Firefox 9 中并不好使,原因不详。

近期评论