在Mac电脑上为Dash制作docSet文档

Dash是mac上的一款查看API的工具,里面可以直接下载大部分的API文档,但是有时候我们如果想把自己手里已有的文档也集成到Dash中,就需要我们自己动手了,其实Dash官方也有教程如何制作docSet的,地址是:http://kapeli.com/docsets  (7. Any HTML Documentation) , 本文是我照着官方的教程,把流程步骤一步一步的记录下来的,大家可以参考一下。


Dash所需的文档都是docSet文件,其实docSet文件就是一个文件夹而已,这个文件夹里面放了最终的html文档,以及根据这些html建好的索引(索引是放在sqlite数据库中),很简单。


下文我以mysql5.1官方的中文文档(html)为例,来说明如何根据html文档一步步创建docSet

1. 从mysql的官网上下载5.1的html中文文档,下载地址为: http://downloads.mysql.com/docs/refman-5.1-zh.html-chapter.zip , 下载后解压缩,会发现里面全都是一些html文件,其中有2个需要关注,一个index.html,一个是ix01.html,第一个是首页的目录,第二个是所有的索引列表,这2个文件里基本上包括了所有的mysql索引,我们后面就要把这2个文件里的内容按dash要求的格式来建立索引。

2. 建立文件夹。本例中我们创建的文档就叫mysql51吧,所以按下列结构创建目录:

[plain]  view plain copy
  1. mkdir -p mysql51.docset/Contents/Resources/Documents/  


3. 把所有的html文档拷贝到Documents文件夹中。


4. 在mysql51.docset/Contents/中创建Info.plist文件,注意文件名的大小写,文件内容如下:

[html]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  
  3. <plist version="1.0">  
  4. <dict>  
  5.     <key>dashIndexFilePath</key>  
  6.     <string>index.html</string>  
  7.     <key>CFBundleIdentifier</key>  
  8.     <string>mysql51</string>  
  9.     <key>CFBundleName</key>  
  10.     <string>mysql51</string>  
  11.     <key>DocSetPlatformFamily</key>  
  12.     <string>mysql51</string>  
  13.     <key>isDashDocset</key>  
  14.     <true/>  
  15. </dict>  
  16. </plist>  

可以看到这个文件就是一个xml文件,里面都是一对一对的key-string配置项,其中:dashIndexFilePath这个key对应的string是index.html,表示在Dash中点击你的文档后,默认的主页是什么,其他的key表示你创建的文档名字和关键字之类的,我这里都写成了mysql51.


5. 创建sqlite索引。索引文件的位置是:mysql51.docset/Contents/Resources/docSet.dsidx ,Mac电脑已经预装了sqlite,所以直接从命令行进入Resources文件夹,在命令行中敲:

[plain]  view plain copy
  1. sqlite3 docSet.dsidx  
这样就进入了sqlite数据库,接下来,创建数据表:

[plain]  view plain copy
  1. CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);  

完成以后敲:.exit 就可以退出sqlite了,这时候你会看到在Resources目录下已经有了一个docSet.dsidx文件,后续我们的索引都会放到刚才创建的searchIndex表中。(在sqlite中输入".exit"就可以退出了,其他命令可以输入".help"查看)

官方教程中其实在创建表以后还创建了一个unique index,我们这里不能这么搞,后面会讲到,我们的文档一个key有多个索引,所以不能是unique。


6. 接下来就是往searchIndex表中插数据了,SQL模板是:

INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES ('name', 'type', 'path');

其中name就是我们的关键字,比如你想在dash中输入一个select就可以查询,那这个select就是关键字;type是关键字的类型,官方支持的有很多,什么Class,Function,Keyword等,我这里偷了个懒,全部用Keyword了;path就是我们的具体文件名称了,可以是带锚点的形式,如:client-side-scripts.html#mysqladmin。


7. 把所有的索引数据都插入到searchIndex以后,docSet文档就制作好了,直接双击mysql51.docSet就可以导入Dash了。


下面说说怎么通过html文件制作索引并插入到sqlite数据库,Dash的官方教程中提供了很多脚本,有python,ruby,php,oc,nodejs等,其实你用什么语言都可以,只要能生成一份sql文件,在sqlite中通过.read 命令导入就行。 让我们用php来尝试一次吧,因为mysql有2个索引文件,一个index.html,一个是ix01.html,我写了2个php的脚本,就是输出一大堆sql:

[php]  view plain copy
  1. <?php  
  2.   
  3. header('Content-type: text/html; charset=utf-8');  
  4. echo "<meta charset='utf-8'/>";  
  5. $dom = new DomDocument;  
  6. @$dom->loadHTMLFile("/Users/xxx/Desktop/docSet/mysql51.docset/Contents/Resources/Documents/index.html");  
  7.   
  8. foreach ($dom->getElementsByTagName("a"as $a) {  
  9.     $href = $a->getAttribute("href");  
  10.     if (substr($href, 0, 1) == "."continue;  
  11.     if (substr($href, 0, 5) == "http:"continue;  
  12.   
  13.     $name = trim($a->nodeValue);  
  14.     $name = trim(preg_replace("#\s+#""", preg_replace("#^([A-Z0-9–]+\.)+#"""$name)));  
  15.     if (empty($name)) continue;  
  16.     $class = "Keyword";  
  17.     $links[$name] = true;  
  18.     echo "INSERT INTO searchIndex(name, type, path) VALUES ('"$name . "','"$class ."','"$href ."');<br/>";  
  19. }  
  20. ?>  


[php]  view plain copy
  1. <?php  
  2.   
  3. header('Content-type: text/html; charset=utf-8');  
  4. echo "<meta charset='utf-8'/>";  
  5. $dom = new DomDocument;  
  6. @$dom->loadHTMLFile("/Users/bokix/Desktop/docSet/mysql51.docset/Contents/Resources/Documents/ix01.html");  
  7.   
  8. foreach ($dom->getElementsByTagName("dt"as $a) {  
  9.     $name = $a->nodeValue;  
  10.     //echo "$name";  
  11.     //echo "<br/>";  
  12.     //echo "===================$name <br/>";  
  13.     $children = $a->childNodes;   
  14.     if($children->length == 1){  
  15.         //echo $name . "has no child <br/>";  
  16.         continue;  
  17.     }  
  18.      for($i = 0; $i < $children->length; $i++)   
  19.         {   
  20.                 $child = $children->item($i);   
  21.             if($i==0){  
  22.                 $name = trim($child->nodeValue);  
  23.                 if(substr($name,-3) == ","){  
  24.                     $name = substr($name,0,$name->length-3);  
  25.                 }  
  26.                                     //$name = mysql_real_escape_string($name);  
  27.             }  
  28.                 if($child->nodeName !="a"){  
  29.                     //echo "[".$child->nodeValue . "]not a anchor <br/>";  
  30.                     continue;  
  31.                 }  
  32.   
  33.                  $href = $child->getAttribute("href");  
  34.                  $hrefName=trim($child->nodeValue);  
  35.                  $class = "Keyword";  
  36.                    
  37.                         //$hrefName = mysql_real_escape_string($hrefName);  
  38.   
  39.                  echo "INSERT  INTO searchIndex(name, type, path) VALUES ('"$name . "','"$class ."','"$href ."');<br/>";  
  40.                  echo "INSERT  INTO searchIndex(name, type, path) VALUES ('"$hrefName . "','"$class ."','"$href ."');<br/>";  
  41.   
  42.         }  
  43.   
  44. }  
  45.   
  46. ?>  




运行以后屏幕上会输出一堆堆sql语句,分别保存到2个文件里,比如说1.sql和2.sql,这里需要注意下,sqlite对于单引号的转义是在单引号前面再加一个单引号,和其他sql不同,而我们的索引html里面,有些name本身就是带有"\'"(斜杠加单引号)的,所以你要手工改一下,还好就2个地方,在sql文件里搜索:\' , 在单引号前再加一个单引号。


sql文件生成以后,把2个sql文件拷贝到docSet.dsidx的目录,开始导入sqlite吧:

[plain]  view plain copy
  1. sqlite3 docSet.dsidx  
  2. .read 1.sql  
  3. .read 2.sql  

 如果sql正确执行,屏幕上不会输出什么,如果输出一大堆sql语句,那说明sql有问题,翻到第一条,看看什么错误,然后修改下重新导入,如果你怕导重复了,也可以把searchIndex表清空然后重新导入。

这是我生成的几个sql例子:

[sql]  view plain copy
  1. INSERT INTO searchIndex(name, type, path) VALUES ('OCT()','Keyword','functions.html#string-functions');  
  2. INSERT INTO searchIndex(name, type, path) VALUES ('字符串函数','Keyword','functions.html#string-functions');  
  3. INSERT INTO searchIndex(name, type, path) VALUES ('OCTET_LENGTH()','Keyword','functions.html#string-functions');  
  4. INSERT INTO searchIndex(name, type, path) VALUES ('字符串函数','Keyword','functions.html#string-functions');  
  5. INSERT INTO searchIndex(name, type, path) VALUES ('ODBC','Keyword','connectors.html#odbc-connector');  
  6. INSERT INTO searchIndex(name, type, path) VALUES ('MySQL Connector/ODBC','Keyword','connectors.html#odbc-connector');  
  7. INSERT INTO searchIndex(name, type, path) VALUES ('partitioning types','Keyword','partitioning.html#partitioning-types');  
  8. INSERT INTO searchIndex(name, type, path) VALUES ('分区类型','Keyword','partitioning.html#partitioning-types');  

你可能感兴趣的:(在Mac电脑上为Dash制作docSet文档)