init
6
download.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<HTML><HEAD><TITLE>Canal Versions</TITLE></HEAD><BODY>
|
||||||
|
<H1>Canal Versions</H1>
|
||||||
|
<TABLE BORDER=0>
|
||||||
|
|
||||||
|
<TR><TD><A HREF="/download/canal.deployer-1.0.2.tar.gz">canal.deployer-1.0.2.tar.gz </TD><TD ALIGN=right>8470464 bytes </TD><TD>Mar 13, 2013 6:49:34 PM</TD></TR></TABLE>
|
||||||
|
</BODY></HTML>
|
||||||
BIN
images/arrow-down.png
Normal file
|
After Width: | Height: | Size: 423 B |
BIN
images/bg.jpg
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
images/bg2.png
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
images/bg_new.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
images/bodybg.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
images/bubble-arrow.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
images/code.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
images/icons.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
1273
images/johnny_automatic_skew_gear.svg
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
images/lineseparator.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/octocat-small.png
Normal file
|
After Width: | Height: | Size: 570 B |
BIN
images/pattern.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
images/tar.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
images/top.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
images/zip.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
446
index.html
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||||
|
<title>Canal by alibaba</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="stylesheets/styles.css">
|
||||||
|
<link rel="stylesheet" href="stylesheets/pygment_trac.css">
|
||||||
|
<script src="javascripts/scale.fix.js"></script>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<header>
|
||||||
|
<h1 class="header">Canal</h1>
|
||||||
|
<p class="header">阿里巴巴mysql数据库binlog的增量订阅&消费组件</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li class="download"><a class="buttons" href="https://github.com/alibaba/canal/zipball/master">Download ZIP</a></li>
|
||||||
|
<li class="download"><a class="buttons" href="https://github.com/alibaba/canal/tarball/master">Download TAR</a></li>
|
||||||
|
<li><a class="buttons github" href="https://github.com/alibaba/canal">View On GitHub</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p class="header">This project is maintained by <a class="header name" href="https://github.com/alibaba">alibaba</a></p>
|
||||||
|
|
||||||
|
|
||||||
|
</header>
|
||||||
|
<section>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p> </p>
|
||||||
|
<h1>背景</h1>
|
||||||
|
<p> 早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务,从此开启了一段新纪元。ps. 目前内部使用的同步,已经支持mysql5.x和oracle部分版本的日志解析</p>
|
||||||
|
<p> </p>
|
||||||
|
<p>基于日志增量订阅&消费支持的业务:</p>
|
||||||
|
<ol>
|
||||||
|
<li>数据库镜像</li>
|
||||||
|
<li>数据库实时备份</li>
|
||||||
|
<li>多级索引 (卖家和买家各自分库索引)</li>
|
||||||
|
<li>search build</li>
|
||||||
|
<li>业务cache刷新</li>
|
||||||
|
<li>价格变化等重要业务消息</li>
|
||||||
|
</ol>
|
||||||
|
<h1>项目介绍</h1>
|
||||||
|
<p> 名称:canal [kə'næl]</p>
|
||||||
|
<p> 译意: 水道/管道/沟渠 </p>
|
||||||
|
<p> 语言: 纯java开发</p>
|
||||||
|
<p> 定位: 基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了mysql</p>
|
||||||
|
<p> </p>
|
||||||
|
<h2>工作原理</h2>
|
||||||
|
<h3>mysql主备复制实现</h3>
|
||||||
|
<p><img src="http://dl.iteye.com/upload/attachment/0080/3086/468c1a14-e7ad-3290-9d3d-44ac501a7227.jpg" alt=""><br> 从上层来看,复制分成三步:</p>
|
||||||
|
<ol>
|
||||||
|
<li>master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看);</li>
|
||||||
|
<li>slave将master的binary log events拷贝到它的中继日志(relay log);</li>
|
||||||
|
<li>slave重做中继日志中的事件,将改变反映它自己的数据。</li>
|
||||||
|
</ol>
|
||||||
|
<h3>canal的工作原理:</h3>
|
||||||
|
<p><img width="590" src="http://dl.iteye.com/upload/attachment/0080/3107/c87b67ba-394c-3086-9577-9db05be04c95.jpg" alt="" height="273"></p>
|
||||||
|
<p>原理相对比较简单:</p>
|
||||||
|
<ol>
|
||||||
|
<li>canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议</li>
|
||||||
|
<li>mysql master收到dump请求,开始推送binary log给slave(也就是canal)</li>
|
||||||
|
<li>canal解析binary log对象(原始为byte流)</li>
|
||||||
|
</ol>
|
||||||
|
<h1>架构</h1>
|
||||||
|
<p><img width="548" src="http://dl.iteye.com/upload/attachment/0080/3126/49550085-0cd2-32fa-86a6-f676db5b597b.jpg" alt="" height="238"></p>
|
||||||
|
<p>说明:</p>
|
||||||
|
<ul>
|
||||||
|
<li>server代表一个canal运行实例,对应于一个jvm</li>
|
||||||
|
<li>instance对应于一个数据队列 (1个server对应1..n个instance)</li>
|
||||||
|
</ul>
|
||||||
|
<p>instance模块:</p>
|
||||||
|
<ul>
|
||||||
|
<li>eventParser (数据源接入,模拟slave协议和master进行交互,协议解析)</li>
|
||||||
|
<li>eventSink (Parser和Store链接器,进行数据过滤,加工,分发的工作)</li>
|
||||||
|
<li>eventStore (数据存储)</li>
|
||||||
|
<li>metaManager (增量订阅&消费信息管理器)</li>
|
||||||
|
</ul>
|
||||||
|
<h3>数据对象格式:<a href="https://github.com/otter-projects/canal/blob/master/protocol/src/main/java/com/alibaba/otter/canal/protocol/EntryProtocol.proto">EntryProtocol.proto</a>
|
||||||
|
</h3>
|
||||||
|
<pre name="code">Entry
|
||||||
|
Header
|
||||||
|
logfileName [binlog文件名]
|
||||||
|
logfileOffset [binlog position]
|
||||||
|
executeTime [发生的变更]
|
||||||
|
schemaName
|
||||||
|
tableName
|
||||||
|
eventType [insert/update/delete类型]
|
||||||
|
entryType [事务头BEGIN/事务尾END/数据ROWDATA]
|
||||||
|
storeValue [byte数据,可展开,对应的类型为RowChange]
|
||||||
|
|
||||||
|
RowChange
|
||||||
|
isDdl [是否是ddl变更操作,比如create table/drop table]
|
||||||
|
sql [具体的ddl sql]
|
||||||
|
rowDatas [具体insert/update/delete的变更数据,可为多条,1个binlog event事件可对应多条变更,比如批处理]
|
||||||
|
beforeColumns [Column类型的数组]
|
||||||
|
afterColumns [Column类型的数组]
|
||||||
|
|
||||||
|
Column
|
||||||
|
index
|
||||||
|
sqlType [jdbc type]
|
||||||
|
name [column name]
|
||||||
|
isKey [是否为主键]
|
||||||
|
updated [是否发生过变更]
|
||||||
|
isNull [值是否为null]
|
||||||
|
value [具体的内容,注意为文本]</pre>
|
||||||
|
<p>说明:</p>
|
||||||
|
<ul>
|
||||||
|
<li>可以提供数据库变更前和变更后的字段内容,针对binlog中没有的name,isKey等信息进行补全</li>
|
||||||
|
<li>可以提供ddl的变更语句</li>
|
||||||
|
</ul>
|
||||||
|
<h1>QuickStart</h1>
|
||||||
|
<h2>几点说明:(mysql初始化)</h2>
|
||||||
|
<p>a. canal的原理是基于mysql binlog技术,所以这里一定需要开启mysql的binlog写入功能,并且配置binlog模式为row. </p>
|
||||||
|
<pre name="code">[mysqld]
|
||||||
|
log-bin=mysql-bin #添加这一行就ok
|
||||||
|
binlog-format=ROW #选择row模式
|
||||||
|
server_id=1 #配置mysql replaction需要定义,不能和canal的slaveId重复</pre>
|
||||||
|
b. canal的原理是模拟自己为mysql slave,所以这里一定需要做为mysql slave的相关权限.</div>
|
||||||
|
<div>
|
||||||
|
<pre name="code">CREATE USER canal IDENTIFIED BY 'canal';
|
||||||
|
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
|
||||||
|
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
|
||||||
|
FLUSH PRIVILEGES;</pre>
|
||||||
|
<p>针对已有的账户可通过grants查询权限:</p>
|
||||||
|
<h2>启动步骤:</h2>
|
||||||
|
<p>1. 下载canal</p>
|
||||||
|
<p>下载部署包</p>
|
||||||
|
<pre name="code">wget http://canal4mysql.googlecode.com/files/canal.deployer-1.0.0.tar.gz</pre>
|
||||||
|
<p>or </p>
|
||||||
|
<p>自己编译 </p>
|
||||||
|
<pre name="code">git clone git@github.com:otter-projects/canal.git
|
||||||
|
cd canal;
|
||||||
|
mvn clean install -Dmaven.test.skip -Denv=release</pre>
|
||||||
|
<p> 编译完成后,会在根目录下产生target/canal.deployer-$version.tar.gz </p>
|
||||||
|
<p> </p>
|
||||||
|
<p>2. 解压缩</p>
|
||||||
|
<pre name="code">mkdir /tmp/canal
|
||||||
|
tar zxvf canal.deployer-1.0.0.tar.gz -C /tmp/canal</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p> 解压完成后,进入/tmp/canal目录,可以看到如下结构:</p>
|
||||||
|
<p> </p>
|
||||||
|
<pre name="code">drwxr-xr-x 2 jianghang jianghang 136 2013-02-05 21:51 bin
|
||||||
|
drwxr-xr-x 4 jianghang jianghang 160 2013-02-05 21:51 conf
|
||||||
|
drwxr-xr-x 2 jianghang jianghang 1.3K 2013-02-05 21:51 lib
|
||||||
|
drwxr-xr-x 2 jianghang jianghang 48 2013-02-05 21:29 logs</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p>3. 配置修改</p>
|
||||||
|
<p> </p>
|
||||||
|
<p>公用参数: </p>
|
||||||
|
<pre name="code">vi conf/canal.properties</pre>
|
||||||
|
<pre name="code">#################################################
|
||||||
|
######### common argument #############
|
||||||
|
#################################################
|
||||||
|
canal.id= 1
|
||||||
|
canal.address=
|
||||||
|
canal.port= 11111
|
||||||
|
canal.zkServers=
|
||||||
|
# flush data to zk
|
||||||
|
canal.zookeeper.flush.period = 1000
|
||||||
|
## memory store RingBuffer size, should be Math.pow(2,n)
|
||||||
|
canal.instance.memory.buffer.size = 32768
|
||||||
|
|
||||||
|
## detecing config
|
||||||
|
canal.instance.detecting.enable = false
|
||||||
|
canal.instance.detecting.sql = insert into retl.xdual values(1,now()) on duplicate key update x=now()
|
||||||
|
canal.instance.detecting.interval.time = 3
|
||||||
|
canal.instance.detecting.retry.threshold = 3
|
||||||
|
canal.instance.detecting.heartbeatHaEnable = false
|
||||||
|
|
||||||
|
# support maximum transaction size, more than the size of the transaction will be cut into multiple transactions delivery
|
||||||
|
canal.instance.transactionn.size = 1024
|
||||||
|
|
||||||
|
# network config
|
||||||
|
canal.instance.network.receiveBufferSize = 16384
|
||||||
|
canal.instance.network.sendBufferSize = 16384
|
||||||
|
canal.instance.network.soTimeout = 30
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
######### destinations #############
|
||||||
|
#################################################
|
||||||
|
canal.destinations= example
|
||||||
|
|
||||||
|
canal.instance.global.mode = spring
|
||||||
|
canal.instance.global.lazy = true ##修改为false,代表立马启动
|
||||||
|
#canal.instance.global.manager.address = 127.0.0.1:1099
|
||||||
|
canal.instance.global.spring.xml = classpath:spring/memory-instance.xml
|
||||||
|
#canal.instance.global.spring.xml = classpath:spring/default-instance.xml</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p>应用参数:</p>
|
||||||
|
<pre name="code">vi conf/example/instance.properties</pre>
|
||||||
|
<pre name="code">#################################################
|
||||||
|
## mysql serverId
|
||||||
|
canal.instance.mysql.slaveId = 1234
|
||||||
|
|
||||||
|
# position info
|
||||||
|
canal.instance.master.address = 127.0.0.1:3306 #改成自己的数据库地址
|
||||||
|
canal.instance.master.journal.name =
|
||||||
|
canal.instance.master.position =
|
||||||
|
canal.instance.master.timestamp =
|
||||||
|
|
||||||
|
#canal.instance.standby.address =
|
||||||
|
#canal.instance.standby.journal.name =
|
||||||
|
#canal.instance.standby.position =
|
||||||
|
#canal.instance.standby.timestamp =
|
||||||
|
|
||||||
|
# username/password
|
||||||
|
canal.instance.dbUsername = retl #改成自己的数据库信息
|
||||||
|
canal.instance.dbPassword = retl #改成自己的数据库信息
|
||||||
|
canal.instance.defaultDatabaseName = #改成自己的数据库信息
|
||||||
|
canal.instance.connectionCharsetNumber = 33 #改成自己的数据库信息
|
||||||
|
canal.instance.connectionCharset = UTF-8 #改成自己的数据库信息
|
||||||
|
|
||||||
|
# table regex
|
||||||
|
canal.instance.filter.regex = .*\\..*
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p> </p>
|
||||||
|
<p> 说明:</p>
|
||||||
|
<ul>
|
||||||
|
<li>canal.instance.connectionCharset 代表数据库的编码方式对应到java中的编码类型,比如UTF-8,GBK , ISO-8859-1</li>
|
||||||
|
<li>canal.instance.connectionCharsetNumber 代表数据库的编码方式对应mysql中的唯一id,详细的映射关系可查看:com.mysql.jdbc.CharsetMapping.INDEX_TO_CHARSET<br>针对常见的编码:<br>utf-8 <=> 33<br>gb2312 <=> 24<br>gbk <=> 28</li>
|
||||||
|
</ul>
|
||||||
|
<p>4. 准备启动</p>
|
||||||
|
<p> </p>
|
||||||
|
<pre name="code">sh bin/startup.sh</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p>5. 查看日志</p>
|
||||||
|
<pre name="code">vi logs/canal/canal.log</pre>
|
||||||
|
<pre name="code">2013-02-05 22:45:27.967 [main] INFO com.alibaba.otter.canal.deployer.CanalLauncher - ## start the canal server.
|
||||||
|
2013-02-05 22:45:28.113 [main] INFO com.alibaba.otter.canal.deployer.CanalController - ## start the canal server[10.1.29.120:11111]
|
||||||
|
2013-02-05 22:45:28.210 [main] INFO com.alibaba.otter.canal.deployer.CanalLauncher - ## the canal server is running now ......</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p> 具体instance的日志:</p>
|
||||||
|
<pre name="code">vi logs/example/example.log</pre>
|
||||||
|
<pre name="code">2013-02-05 22:50:45.636 [main] INFO c.a.o.c.i.spring.support.PropertyPlaceholderConfigurer - Loading properties file from class path resource [canal.properties]
|
||||||
|
2013-02-05 22:50:45.641 [main] INFO c.a.o.c.i.spring.support.PropertyPlaceholderConfigurer - Loading properties file from class path resource [example/instance.properties]
|
||||||
|
2013-02-05 22:50:45.803 [main] INFO c.a.otter.canal.instance.spring.CanalInstanceWithSpring - start CannalInstance for 1-example
|
||||||
|
2013-02-05 22:50:45.810 [main] INFO c.a.otter.canal.instance.spring.CanalInstanceWithSpring - start successful....</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p>6. 关闭</p>
|
||||||
|
<pre name="code">sh bin/stop.sh</pre>
|
||||||
|
<p> </p>
|
||||||
|
<p>it's over. </p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>ClientExample</h1>
|
||||||
|
|
||||||
|
<p>依赖配置:(目前暂未正式发布到mvn仓库,所以需要各位下载canal源码后手工执行下mvn clean install -Dmaven.test.skip)</p>
|
||||||
|
|
||||||
|
<pre name="code"><dependency>
|
||||||
|
<groupId>com.alibaba.otter</groupId>
|
||||||
|
<artifactId>canal.client</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency></pre>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>1. 创建mvn标准工程:</p>
|
||||||
|
|
||||||
|
<pre name="code">mvn archetype:create -DgroupId=com.alibaba.otter -DartifactId=canal.sample</pre>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>2. 修改pom.xml,添加依赖</p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>3. ClientSample代码</p>
|
||||||
|
|
||||||
|
<pre name="code">package com.alibaba.otter.canal.sample;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.alibaba.otter.canal.common.utils.AddressUtils;
|
||||||
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalEntry.Column;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalEntry.Entry;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalEntry.EntryType;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalEntry.EventType;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalEntry.RowChange;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalEntry.RowData;
|
||||||
|
|
||||||
|
public class SimpleCanalClientExample {
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
// 创建链接
|
||||||
|
CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress(AddressUtils.getHostIp(),
|
||||||
|
11111), "example", "", "");
|
||||||
|
int batchSize = 1000;
|
||||||
|
int emptyCount = 0;
|
||||||
|
try {
|
||||||
|
connector.connect();
|
||||||
|
connector.subscribe(".*\\..*");
|
||||||
|
connector.rollback();
|
||||||
|
int totalEmtryCount = 120;
|
||||||
|
while (emptyCount < totalEmtryCount) {
|
||||||
|
Message message = connector.getWithoutAck(batchSize); // 获取指定数量的数据
|
||||||
|
long batchId = message.getId();
|
||||||
|
int size = message.getEntries().size();
|
||||||
|
if (batchId == -1 || size == 0) {
|
||||||
|
emptyCount++;
|
||||||
|
System.out.println("empty count : " + emptyCount);
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emptyCount = 0;
|
||||||
|
// System.out.printf("message[batchId=%s,size=%s] \n", batchId, size);
|
||||||
|
printEntry(message.getEntries());
|
||||||
|
}
|
||||||
|
|
||||||
|
connector.ack(batchId); // 提交确认
|
||||||
|
// connector.rollback(batchId); // 处理失败, 回滚数据
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("empty too many times, exit");
|
||||||
|
} finally {
|
||||||
|
connector.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printEntry(List<Entry> entrys) {
|
||||||
|
for (Entry entry : entrys) {
|
||||||
|
if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RowChange rowChage = null;
|
||||||
|
try {
|
||||||
|
rowChage = RowChange.parseFrom(entry.getStoreValue());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(),
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventType eventType = rowChage.getEventType();
|
||||||
|
System.out.println(String.format("================> binlog[%s:%s] , name[%s,%s] , eventType : %s",
|
||||||
|
entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
|
||||||
|
entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
|
||||||
|
eventType));
|
||||||
|
|
||||||
|
for (RowData rowData : rowChage.getRowDatasList()) {
|
||||||
|
if (eventType == EventType.DELETE) {
|
||||||
|
printColumn(rowData.getBeforeColumnsList());
|
||||||
|
} else if (eventType == EventType.INSERT) {
|
||||||
|
printColumn(rowData.getAfterColumnsList());
|
||||||
|
} else {
|
||||||
|
System.out.println("-------> before");
|
||||||
|
printColumn(rowData.getBeforeColumnsList());
|
||||||
|
System.out.println("-------> after");
|
||||||
|
printColumn(rowData.getAfterColumnsList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printColumn(List<Column> columns) {
|
||||||
|
for (Column column : columns) {
|
||||||
|
System.out.println(column.getName() + " : " + column.getValue() + " update=" + column.getUpdated());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>4. 运行Client</p>
|
||||||
|
|
||||||
|
<p>首先启动Canal Server,可参加QuickStart : <a href="/blogs/1796070">http://agapple.iteye.com/blogs/1796070</a></p>
|
||||||
|
|
||||||
|
<p>启动Canal Client后,可以从控制台从看到类似消息:</p>
|
||||||
|
|
||||||
|
<pre name="code">empty count : 1
|
||||||
|
empty count : 2
|
||||||
|
empty count : 3
|
||||||
|
empty count : 4</pre>
|
||||||
|
|
||||||
|
<p> 此时代表当前数据库无变更数据</p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>5. 触发数据库变更</p>
|
||||||
|
|
||||||
|
<pre name="code">mysql> use test;
|
||||||
|
Database changed
|
||||||
|
mysql> CREATE TABLE `xdual` (
|
||||||
|
-> `ID` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
-> `X` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
-> PRIMARY KEY (`ID`)
|
||||||
|
-> ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ;
|
||||||
|
Query OK, 0 rows affected (0.06 sec)
|
||||||
|
|
||||||
|
mysql> insert into xdual(id,x) values(null,now());Query OK, 1 row affected (0.06 sec)</pre>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>可以从控制台中看到:</p>
|
||||||
|
|
||||||
|
<pre name="code">empty count : 1
|
||||||
|
empty count : 2
|
||||||
|
empty count : 3
|
||||||
|
empty count : 4
|
||||||
|
================> binlog[mysql-bin.001946:313661577] , name[test,xdual] , eventType : INSERT
|
||||||
|
ID : 4 update=true
|
||||||
|
X : 2013-02-05 23:29:46 update=true</pre>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<h2>最后:</h2>
|
||||||
|
|
||||||
|
<p> 整个代码在附件中可以下载,如有问题可及时联系。 </p>
|
||||||
|
|
||||||
|
<p></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p></p><div>
|
||||||
|
<a href="http://dl.iteye.com/topics/download/7a893f19-bafb-313a-8a7a-e371a4265ad9">canal.sample.tar.gz</a> (2.2 KB)
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<footer>
|
||||||
|
<p><small>Hosted on <a href="https://pages.github.com">GitHub Pages</a> using the Dinky theme</small></p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
<!--[if !IE]><script>fixScale(document);</script><![endif]-->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
try {
|
||||||
|
var pageTracker = _gat._getTracker("UA-10379866-5");
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
} catch(err) {}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4
javascripts/libs/jquery-1.7.1.min.js
vendored
Executable file
771
javascripts/libs/marked.js
Executable file
@@ -0,0 +1,771 @@
|
|||||||
|
/**
|
||||||
|
* marked - A markdown parser (https://github.com/chjj/marked)
|
||||||
|
* Copyright (c) 2011-2012, Christopher Jeffrey. (MIT Licensed)
|
||||||
|
*/
|
||||||
|
|
||||||
|
;(function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Block-Level Grammar
|
||||||
|
*/
|
||||||
|
|
||||||
|
var block = {
|
||||||
|
newline: /^\n+/,
|
||||||
|
code: /^( {4}[^\n]+\n*)+/,
|
||||||
|
fences: noop,
|
||||||
|
hr: /^( *[\-*_]){3,} *(?:\n+|$)/,
|
||||||
|
heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
|
||||||
|
lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
|
||||||
|
blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
|
||||||
|
list: /^( *)([*+-]|\d+\.) [^\0]+?(?:\n{2,}(?! )(?!\1bullet)\n*|\s*$)/,
|
||||||
|
html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
|
||||||
|
def: /^ *\[([^\]]+)\]: *([^\s]+)(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
|
||||||
|
paragraph: /^([^\n]+\n?(?!body))+\n*/,
|
||||||
|
text: /^[^\n]+/
|
||||||
|
};
|
||||||
|
|
||||||
|
block.list = replace(block.list)
|
||||||
|
('bullet', /(?:[*+-](?!(?: *[-*]){2,})|\d+\.)/)
|
||||||
|
();
|
||||||
|
|
||||||
|
block.html = replace(block.html)
|
||||||
|
('comment', /<!--[^\0]*?-->/)
|
||||||
|
('closed', /<(tag)[^\0]+?<\/\1>/)
|
||||||
|
('closing', /<tag(?!:\/|@)\b(?:"[^"]*"|'[^']*'|[^'">])*?>/)
|
||||||
|
(/tag/g, tag())
|
||||||
|
();
|
||||||
|
|
||||||
|
block.paragraph = (function() {
|
||||||
|
var paragraph = block.paragraph.source
|
||||||
|
, body = [];
|
||||||
|
|
||||||
|
(function push(rule) {
|
||||||
|
rule = block[rule] ? block[rule].source : rule;
|
||||||
|
body.push(rule.replace(/(^|[^\[])\^/g, '$1'));
|
||||||
|
return push;
|
||||||
|
})
|
||||||
|
('hr')
|
||||||
|
('heading')
|
||||||
|
('lheading')
|
||||||
|
('blockquote')
|
||||||
|
('<' + tag())
|
||||||
|
('def');
|
||||||
|
|
||||||
|
return new
|
||||||
|
RegExp(paragraph.replace('body', body.join('|')));
|
||||||
|
})();
|
||||||
|
|
||||||
|
block.normal = {
|
||||||
|
fences: block.fences,
|
||||||
|
paragraph: block.paragraph
|
||||||
|
};
|
||||||
|
|
||||||
|
block.gfm = {
|
||||||
|
fences: /^ *``` *(\w+)? *\n([^\0]+?)\s*``` *(?:\n+|$)/,
|
||||||
|
paragraph: /^/
|
||||||
|
};
|
||||||
|
|
||||||
|
block.gfm.paragraph = replace(block.paragraph)
|
||||||
|
('(?!', '(?!' + block.gfm.fences.source.replace(/(^|[^\[])\^/g, '$1') + '|')
|
||||||
|
();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Block Lexer
|
||||||
|
*/
|
||||||
|
|
||||||
|
block.lexer = function(src) {
|
||||||
|
var tokens = [];
|
||||||
|
|
||||||
|
tokens.links = {};
|
||||||
|
|
||||||
|
src = src
|
||||||
|
.replace(/\r\n|\r/g, '\n')
|
||||||
|
.replace(/\t/g, ' ');
|
||||||
|
|
||||||
|
return block.token(src, tokens, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
block.token = function(src, tokens, top) {
|
||||||
|
var src = src.replace(/^ +$/gm, '')
|
||||||
|
, next
|
||||||
|
, loose
|
||||||
|
, cap
|
||||||
|
, item
|
||||||
|
, space
|
||||||
|
, i
|
||||||
|
, l;
|
||||||
|
|
||||||
|
while (src) {
|
||||||
|
// newline
|
||||||
|
if (cap = block.newline.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
if (cap[0].length > 1) {
|
||||||
|
tokens.push({
|
||||||
|
type: 'space'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// code
|
||||||
|
if (cap = block.code.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
cap = cap[0].replace(/^ {4}/gm, '');
|
||||||
|
tokens.push({
|
||||||
|
type: 'code',
|
||||||
|
text: !options.pedantic
|
||||||
|
? cap.replace(/\n+$/, '')
|
||||||
|
: cap
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fences (gfm)
|
||||||
|
if (cap = block.fences.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.push({
|
||||||
|
type: 'code',
|
||||||
|
lang: cap[1],
|
||||||
|
text: cap[2]
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// heading
|
||||||
|
if (cap = block.heading.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.push({
|
||||||
|
type: 'heading',
|
||||||
|
depth: cap[1].length,
|
||||||
|
text: cap[2]
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lheading
|
||||||
|
if (cap = block.lheading.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.push({
|
||||||
|
type: 'heading',
|
||||||
|
depth: cap[2] === '=' ? 1 : 2,
|
||||||
|
text: cap[1]
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hr
|
||||||
|
if (cap = block.hr.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.push({
|
||||||
|
type: 'hr'
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// blockquote
|
||||||
|
if (cap = block.blockquote.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
|
||||||
|
tokens.push({
|
||||||
|
type: 'blockquote_start'
|
||||||
|
});
|
||||||
|
|
||||||
|
cap = cap[0].replace(/^ *> ?/gm, '');
|
||||||
|
|
||||||
|
// Pass `top` to keep the current
|
||||||
|
// "toplevel" state. This is exactly
|
||||||
|
// how markdown.pl works.
|
||||||
|
block.token(cap, tokens, top);
|
||||||
|
|
||||||
|
tokens.push({
|
||||||
|
type: 'blockquote_end'
|
||||||
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// list
|
||||||
|
if (cap = block.list.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
|
||||||
|
tokens.push({
|
||||||
|
type: 'list_start',
|
||||||
|
ordered: isFinite(cap[2])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get each top-level item.
|
||||||
|
cap = cap[0].match(
|
||||||
|
/^( *)([*+-]|\d+\.) [^\n]*(?:\n(?!\1(?:[*+-]|\d+\.) )[^\n]*)*/gm
|
||||||
|
);
|
||||||
|
|
||||||
|
next = false;
|
||||||
|
l = cap.length;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (; i < l; i++) {
|
||||||
|
item = cap[i];
|
||||||
|
|
||||||
|
// Remove the list item's bullet
|
||||||
|
// so it is seen as the next token.
|
||||||
|
space = item.length;
|
||||||
|
item = item.replace(/^ *([*+-]|\d+\.) +/, '');
|
||||||
|
|
||||||
|
// Outdent whatever the
|
||||||
|
// list item contains. Hacky.
|
||||||
|
if (~item.indexOf('\n ')) {
|
||||||
|
space -= item.length;
|
||||||
|
item = !options.pedantic
|
||||||
|
? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
|
||||||
|
: item.replace(/^ {1,4}/gm, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine whether item is loose or not.
|
||||||
|
// Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
|
||||||
|
// for discount behavior.
|
||||||
|
loose = next || /\n\n(?!\s*$)/.test(item);
|
||||||
|
if (i !== l - 1) {
|
||||||
|
next = item[item.length-1] === '\n';
|
||||||
|
if (!loose) loose = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.push({
|
||||||
|
type: loose
|
||||||
|
? 'loose_item_start'
|
||||||
|
: 'list_item_start'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Recurse.
|
||||||
|
block.token(item, tokens);
|
||||||
|
|
||||||
|
tokens.push({
|
||||||
|
type: 'list_item_end'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.push({
|
||||||
|
type: 'list_end'
|
||||||
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// html
|
||||||
|
if (cap = block.html.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.push({
|
||||||
|
type: 'html',
|
||||||
|
pre: cap[1] === 'pre',
|
||||||
|
text: cap[0]
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// def
|
||||||
|
if (top && (cap = block.def.exec(src))) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.links[cap[1].toLowerCase()] = {
|
||||||
|
href: cap[2],
|
||||||
|
title: cap[3]
|
||||||
|
};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// top-level paragraph
|
||||||
|
if (top && (cap = block.paragraph.exec(src))) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.push({
|
||||||
|
type: 'paragraph',
|
||||||
|
text: cap[0]
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// text
|
||||||
|
if (cap = block.text.exec(src)) {
|
||||||
|
// Top-level should never reach here.
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
tokens.push({
|
||||||
|
type: 'text',
|
||||||
|
text: cap[0]
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inline Processing
|
||||||
|
*/
|
||||||
|
|
||||||
|
var inline = {
|
||||||
|
escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
|
||||||
|
autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
|
||||||
|
url: noop,
|
||||||
|
tag: /^<!--[^\0]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
|
||||||
|
link: /^!?\[(inside)\]\(href\)/,
|
||||||
|
reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
|
||||||
|
nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
|
||||||
|
strong: /^__([^\0]+?)__(?!_)|^\*\*([^\0]+?)\*\*(?!\*)/,
|
||||||
|
em: /^\b_((?:__|[^\0])+?)_\b|^\*((?:\*\*|[^\0])+?)\*(?!\*)/,
|
||||||
|
code: /^(`+)([^\0]*?[^`])\1(?!`)/,
|
||||||
|
br: /^ {2,}\n(?!\s*$)/,
|
||||||
|
text: /^[^\0]+?(?=[\\<!\[_*`]| {2,}\n|$)/
|
||||||
|
};
|
||||||
|
|
||||||
|
inline._linkInside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
|
||||||
|
inline._linkHref = /\s*<?([^\s]*?)>?(?:\s+['"]([^\0]*?)['"])?\s*/;
|
||||||
|
|
||||||
|
inline.link = replace(inline.link)
|
||||||
|
('inside', inline._linkInside)
|
||||||
|
('href', inline._linkHref)
|
||||||
|
();
|
||||||
|
|
||||||
|
inline.reflink = replace(inline.reflink)
|
||||||
|
('inside', inline._linkInside)
|
||||||
|
();
|
||||||
|
|
||||||
|
inline.normal = {
|
||||||
|
url: inline.url,
|
||||||
|
strong: inline.strong,
|
||||||
|
em: inline.em,
|
||||||
|
text: inline.text
|
||||||
|
};
|
||||||
|
|
||||||
|
inline.pedantic = {
|
||||||
|
strong: /^__(?=\S)([^\0]*?\S)__(?!_)|^\*\*(?=\S)([^\0]*?\S)\*\*(?!\*)/,
|
||||||
|
em: /^_(?=\S)([^\0]*?\S)_(?!_)|^\*(?=\S)([^\0]*?\S)\*(?!\*)/
|
||||||
|
};
|
||||||
|
|
||||||
|
inline.gfm = {
|
||||||
|
url: /^(https?:\/\/[^\s]+[^.,:;"')\]\s])/,
|
||||||
|
text: /^[^\0]+?(?=[\\<!\[_*`]|https?:\/\/| {2,}\n|$)/
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inline Lexer
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline.lexer = function(src) {
|
||||||
|
var out = ''
|
||||||
|
, links = tokens.links
|
||||||
|
, link
|
||||||
|
, text
|
||||||
|
, href
|
||||||
|
, cap;
|
||||||
|
|
||||||
|
while (src) {
|
||||||
|
// escape
|
||||||
|
if (cap = inline.escape.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += cap[1];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// autolink
|
||||||
|
if (cap = inline.autolink.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
if (cap[2] === '@') {
|
||||||
|
text = cap[1][6] === ':'
|
||||||
|
? mangle(cap[1].substring(7))
|
||||||
|
: mangle(cap[1]);
|
||||||
|
href = mangle('mailto:') + text;
|
||||||
|
} else {
|
||||||
|
text = escape(cap[1]);
|
||||||
|
href = text;
|
||||||
|
}
|
||||||
|
out += '<a href="'
|
||||||
|
+ href
|
||||||
|
+ '">'
|
||||||
|
+ text
|
||||||
|
+ '</a>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// url (gfm)
|
||||||
|
if (cap = inline.url.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
text = escape(cap[1]);
|
||||||
|
href = text;
|
||||||
|
out += '<a href="'
|
||||||
|
+ href
|
||||||
|
+ '">'
|
||||||
|
+ text
|
||||||
|
+ '</a>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tag
|
||||||
|
if (cap = inline.tag.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += options.sanitize
|
||||||
|
? escape(cap[0])
|
||||||
|
: cap[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// link
|
||||||
|
if (cap = inline.link.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += outputLink(cap, {
|
||||||
|
href: cap[2],
|
||||||
|
title: cap[3]
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reflink, nolink
|
||||||
|
if ((cap = inline.reflink.exec(src))
|
||||||
|
|| (cap = inline.nolink.exec(src))) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
|
||||||
|
link = links[link.toLowerCase()];
|
||||||
|
if (!link || !link.href) {
|
||||||
|
out += cap[0][0];
|
||||||
|
src = cap[0].substring(1) + src;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out += outputLink(cap, link);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// strong
|
||||||
|
if (cap = inline.strong.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += '<strong>'
|
||||||
|
+ inline.lexer(cap[2] || cap[1])
|
||||||
|
+ '</strong>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// em
|
||||||
|
if (cap = inline.em.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += '<em>'
|
||||||
|
+ inline.lexer(cap[2] || cap[1])
|
||||||
|
+ '</em>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// code
|
||||||
|
if (cap = inline.code.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += '<code>'
|
||||||
|
+ escape(cap[2], true)
|
||||||
|
+ '</code>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// br
|
||||||
|
if (cap = inline.br.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += '<br>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// text
|
||||||
|
if (cap = inline.text.exec(src)) {
|
||||||
|
src = src.substring(cap[0].length);
|
||||||
|
out += escape(cap[0]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
var outputLink = function(cap, link) {
|
||||||
|
if (cap[0][0] !== '!') {
|
||||||
|
return '<a href="'
|
||||||
|
+ escape(link.href)
|
||||||
|
+ '"'
|
||||||
|
+ (link.title
|
||||||
|
? ' title="'
|
||||||
|
+ escape(link.title)
|
||||||
|
+ '"'
|
||||||
|
: '')
|
||||||
|
+ '>'
|
||||||
|
+ inline.lexer(cap[1])
|
||||||
|
+ '</a>';
|
||||||
|
} else {
|
||||||
|
return '<img src="'
|
||||||
|
+ escape(link.href)
|
||||||
|
+ '" alt="'
|
||||||
|
+ escape(cap[1])
|
||||||
|
+ '"'
|
||||||
|
+ (link.title
|
||||||
|
? ' title="'
|
||||||
|
+ escape(link.title)
|
||||||
|
+ '"'
|
||||||
|
: '')
|
||||||
|
+ '>';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parsing
|
||||||
|
*/
|
||||||
|
|
||||||
|
var tokens
|
||||||
|
, token;
|
||||||
|
|
||||||
|
var next = function() {
|
||||||
|
return token = tokens.pop();
|
||||||
|
};
|
||||||
|
|
||||||
|
var tok = function() {
|
||||||
|
switch (token.type) {
|
||||||
|
case 'space': {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
case 'hr': {
|
||||||
|
return '<hr>\n';
|
||||||
|
}
|
||||||
|
case 'heading': {
|
||||||
|
return '<h'
|
||||||
|
+ token.depth
|
||||||
|
+ '>'
|
||||||
|
+ inline.lexer(token.text)
|
||||||
|
+ '</h'
|
||||||
|
+ token.depth
|
||||||
|
+ '>\n';
|
||||||
|
}
|
||||||
|
case 'code': {
|
||||||
|
return '<pre><code'
|
||||||
|
+ (token.lang
|
||||||
|
? ' class="'
|
||||||
|
+ token.lang
|
||||||
|
+ '"'
|
||||||
|
: '')
|
||||||
|
+ '>'
|
||||||
|
+ (token.escaped
|
||||||
|
? token.text
|
||||||
|
: escape(token.text, true))
|
||||||
|
+ '</code></pre>\n';
|
||||||
|
}
|
||||||
|
case 'blockquote_start': {
|
||||||
|
var body = '';
|
||||||
|
|
||||||
|
while (next().type !== 'blockquote_end') {
|
||||||
|
body += tok();
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<blockquote>\n'
|
||||||
|
+ body
|
||||||
|
+ '</blockquote>\n';
|
||||||
|
}
|
||||||
|
case 'list_start': {
|
||||||
|
var type = token.ordered ? 'ol' : 'ul'
|
||||||
|
, body = '';
|
||||||
|
|
||||||
|
while (next().type !== 'list_end') {
|
||||||
|
body += tok();
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<'
|
||||||
|
+ type
|
||||||
|
+ '>\n'
|
||||||
|
+ body
|
||||||
|
+ '</'
|
||||||
|
+ type
|
||||||
|
+ '>\n';
|
||||||
|
}
|
||||||
|
case 'list_item_start': {
|
||||||
|
var body = '';
|
||||||
|
|
||||||
|
while (next().type !== 'list_item_end') {
|
||||||
|
body += token.type === 'text'
|
||||||
|
? parseText()
|
||||||
|
: tok();
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<li>'
|
||||||
|
+ body
|
||||||
|
+ '</li>\n';
|
||||||
|
}
|
||||||
|
case 'loose_item_start': {
|
||||||
|
var body = '';
|
||||||
|
|
||||||
|
while (next().type !== 'list_item_end') {
|
||||||
|
body += tok();
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<li>'
|
||||||
|
+ body
|
||||||
|
+ '</li>\n';
|
||||||
|
}
|
||||||
|
case 'html': {
|
||||||
|
if (options.sanitize) {
|
||||||
|
return inline.lexer(token.text);
|
||||||
|
}
|
||||||
|
return !token.pre && !options.pedantic
|
||||||
|
? inline.lexer(token.text)
|
||||||
|
: token.text;
|
||||||
|
}
|
||||||
|
case 'paragraph': {
|
||||||
|
return '<p>'
|
||||||
|
+ inline.lexer(token.text)
|
||||||
|
+ '</p>\n';
|
||||||
|
}
|
||||||
|
case 'text': {
|
||||||
|
return '<p>'
|
||||||
|
+ parseText()
|
||||||
|
+ '</p>\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var parseText = function() {
|
||||||
|
var body = token.text
|
||||||
|
, top;
|
||||||
|
|
||||||
|
while ((top = tokens[tokens.length-1])
|
||||||
|
&& top.type === 'text') {
|
||||||
|
body += '\n' + next().text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inline.lexer(body);
|
||||||
|
};
|
||||||
|
|
||||||
|
var parse = function(src) {
|
||||||
|
tokens = src.reverse();
|
||||||
|
|
||||||
|
var out = '';
|
||||||
|
while (next()) {
|
||||||
|
out += tok();
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens = null;
|
||||||
|
token = null;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers
|
||||||
|
*/
|
||||||
|
|
||||||
|
var escape = function(html, encode) {
|
||||||
|
return html
|
||||||
|
.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
};
|
||||||
|
|
||||||
|
var mangle = function(text) {
|
||||||
|
var out = ''
|
||||||
|
, l = text.length
|
||||||
|
, i = 0
|
||||||
|
, ch;
|
||||||
|
|
||||||
|
for (; i < l; i++) {
|
||||||
|
ch = text.charCodeAt(i);
|
||||||
|
if (Math.random() > 0.5) {
|
||||||
|
ch = 'x' + ch.toString(16);
|
||||||
|
}
|
||||||
|
out += '&#' + ch + ';';
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
function tag() {
|
||||||
|
var tag = '(?!(?:'
|
||||||
|
+ 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
|
||||||
|
+ '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
|
||||||
|
+ '|span|br|wbr|ins|del|img)\\b)\\w+';
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
function replace(regex) {
|
||||||
|
regex = regex.source;
|
||||||
|
return function self(name, val) {
|
||||||
|
if (!name) return new RegExp(regex);
|
||||||
|
regex = regex.replace(name, val.source || val);
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function noop() {}
|
||||||
|
noop.exec = noop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marked
|
||||||
|
*/
|
||||||
|
|
||||||
|
var marked = function(src, opt) {
|
||||||
|
setOptions(opt);
|
||||||
|
return parse(block.lexer(src));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options
|
||||||
|
*/
|
||||||
|
|
||||||
|
var options
|
||||||
|
, defaults;
|
||||||
|
|
||||||
|
var setOptions = function(opt) {
|
||||||
|
if (!opt) opt = defaults;
|
||||||
|
if (options === opt) return;
|
||||||
|
options = opt;
|
||||||
|
|
||||||
|
if (options.gfm) {
|
||||||
|
block.fences = block.gfm.fences;
|
||||||
|
block.paragraph = block.gfm.paragraph;
|
||||||
|
inline.text = inline.gfm.text;
|
||||||
|
inline.url = inline.gfm.url;
|
||||||
|
} else {
|
||||||
|
block.fences = block.normal.fences;
|
||||||
|
block.paragraph = block.normal.paragraph;
|
||||||
|
inline.text = inline.normal.text;
|
||||||
|
inline.url = inline.normal.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.pedantic) {
|
||||||
|
inline.em = inline.pedantic.em;
|
||||||
|
inline.strong = inline.pedantic.strong;
|
||||||
|
} else {
|
||||||
|
inline.em = inline.normal.em;
|
||||||
|
inline.strong = inline.normal.strong;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
marked.options =
|
||||||
|
marked.setOptions = function(opt) {
|
||||||
|
defaults = opt;
|
||||||
|
setOptions(opt);
|
||||||
|
};
|
||||||
|
|
||||||
|
marked.options({
|
||||||
|
gfm: true,
|
||||||
|
pedantic: false,
|
||||||
|
sanitize: false
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose
|
||||||
|
*/
|
||||||
|
|
||||||
|
marked.parser = function(src, opt) {
|
||||||
|
setOptions(opt);
|
||||||
|
return parse(src);
|
||||||
|
};
|
||||||
|
|
||||||
|
marked.lexer = function(src, opt) {
|
||||||
|
setOptions(opt);
|
||||||
|
return block.lexer(src);
|
||||||
|
};
|
||||||
|
|
||||||
|
marked.parse = marked;
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
module.exports = marked;
|
||||||
|
} else {
|
||||||
|
this.marked = marked;
|
||||||
|
}
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
4
javascripts/libs/modernizr-2.0.6.min.js
vendored
Executable file
278
javascripts/releasenotes.js
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
* Copyright, Cedric Dugas,
|
||||||
|
* Do not sell or redistribute
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
(function($)
|
||||||
|
{
|
||||||
|
// mardown parser options, do not touch
|
||||||
|
marked.setOptions({
|
||||||
|
gfm: true,
|
||||||
|
pedantic: false,
|
||||||
|
sanitize: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Default setting
|
||||||
|
var defaultSettings = {
|
||||||
|
milestonesShown : 10,
|
||||||
|
// If you want to show private repo
|
||||||
|
// You need to add repo credentials in api.php
|
||||||
|
phpApi : false,
|
||||||
|
phpApiPath : '/',
|
||||||
|
showDescription : true,
|
||||||
|
showComments : true,
|
||||||
|
// Used if phpApi is set to false
|
||||||
|
repo : 'rails',
|
||||||
|
username : 'rails'
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.releaseNotes = function(settings){
|
||||||
|
settings = $.extend({}, defaultSettings, settings || {});
|
||||||
|
var apiPath = settings.phpApiPath+"api.php";
|
||||||
|
var respType = (settings.phpApi) ? "json" : "jsonp";
|
||||||
|
|
||||||
|
var releases = {
|
||||||
|
load: function(el){
|
||||||
|
var _this = this;
|
||||||
|
this.$el = $(el);
|
||||||
|
this.loadEvents();
|
||||||
|
|
||||||
|
var options = $.extend(settings, {
|
||||||
|
state: "closed",
|
||||||
|
action: "milestones",
|
||||||
|
sort:"due_date"
|
||||||
|
});
|
||||||
|
|
||||||
|
this.callApi(options).success(function(resp){
|
||||||
|
if(resp.data) resp= resp.data;
|
||||||
|
_this.showMilestones(resp);
|
||||||
|
}).error(function(resp){
|
||||||
|
console.log(resp)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
loadEvents : function(){
|
||||||
|
var _this = this;
|
||||||
|
if(settings.showDescription) this.$el.delegate(".issue", "click", function(){ _this.loadIssueDesc(this); return false;});
|
||||||
|
if(settings.showComments) this.$el.delegate(".btnComments", "click", function(){ _this.loadComments(this); return false;});
|
||||||
|
},
|
||||||
|
loadIssueDesc : function(el){
|
||||||
|
var $issue = $(el);
|
||||||
|
var data = $issue.data("issue");
|
||||||
|
$bigIssue = $issue.find(".issueBig");
|
||||||
|
|
||||||
|
if(!$bigIssue.is(":visible")){
|
||||||
|
$(".issueBig").not($bigIssue).slideUp();
|
||||||
|
$bigIssue.find(".container").html(components.bigIssue(data, settings.showComments));
|
||||||
|
$bigIssue.slideDown();
|
||||||
|
}else{
|
||||||
|
$bigIssue.slideUp();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showMilestones : function(milestones){
|
||||||
|
var _this = this;
|
||||||
|
milestones.sort(this.sortDate);
|
||||||
|
$.each(milestones, function(i, milestone){
|
||||||
|
if(i == settings.milestonesShown) return false;
|
||||||
|
milestone.prettyDate = (milestone.due_on) ? _this.getPrettyDate(milestone.due_on) : _this.getPrettyDate(milestone.created_at);
|
||||||
|
_this.$el.append(components.milestone(milestone));
|
||||||
|
var options = $.extend(settings, {
|
||||||
|
milestone: milestone.number,
|
||||||
|
sort:"created",
|
||||||
|
action:"issues",
|
||||||
|
state:"closed"
|
||||||
|
});
|
||||||
|
_this.callApi(options).success(function(resp, textStatus, jqXHR){
|
||||||
|
if(resp.data) resp= resp.data;
|
||||||
|
_this.showIssues(resp);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
loadComments : function(el){
|
||||||
|
|
||||||
|
var _this =this;
|
||||||
|
var issueid =$(el).attr("data-issue-id");
|
||||||
|
$(el).fadeOut().slideUp();
|
||||||
|
|
||||||
|
var options = $.extend(settings, {
|
||||||
|
issueid:issueid,
|
||||||
|
action:"comments"
|
||||||
|
});
|
||||||
|
|
||||||
|
this.callApi(options).success(function(resp, textStatus, jqXHR){
|
||||||
|
if(resp.data) resp= resp.data;
|
||||||
|
_this.showComments(resp, issueid);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showComments : function(comments,issueid){
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var $commentContainer = _this.$el.find("#issue"+issueid).find(".comments").empty();
|
||||||
|
$.each(comments, function(i, comment){
|
||||||
|
comment.prettyDate = _this.getPrettyDate(comment.created_at);
|
||||||
|
$commentContainer.append(components.comment(comment, issueid));
|
||||||
|
});
|
||||||
|
$commentContainer.slideDown();
|
||||||
|
},
|
||||||
|
showIssues : function(issues){
|
||||||
|
var _this = this;
|
||||||
|
var jqMilestone = _this.$el.find("[data-id-milestone="+issues[0].milestone.number+"]");
|
||||||
|
var jqMilestoneIssues = jqMilestone.find(".issues");
|
||||||
|
issues.sort(this.sortLabel);
|
||||||
|
$.each(issues, function(i, issue){
|
||||||
|
issue.prettyDate = _this.getPrettyDate(issue.closed_at);
|
||||||
|
jqMilestoneIssues.append(components.issue(issue));
|
||||||
|
});
|
||||||
|
jqMilestone.addClass("separator");
|
||||||
|
if(settings.showDescription) jqMilestone.find(".issue").addClass("cursor");
|
||||||
|
},
|
||||||
|
getPrettyDate : function(date){
|
||||||
|
var dateFormat = "";
|
||||||
|
var date = date.split("T");
|
||||||
|
var dateArray = date[0].split("-");
|
||||||
|
var dateObj = new Date(dateArray[0],(dateArray[1]-1),dateArray[2]);
|
||||||
|
|
||||||
|
var weekday=new Array("Sunday","Monday","Tuesday","Wednesday","Thursday", "Friday","Saturday");
|
||||||
|
var monthname=new Array("January","February","March","April","May","June","July","August", "September","October","November","December");
|
||||||
|
dateFormat += weekday[dateObj.getDay()] + ", ";
|
||||||
|
dateFormat += monthname[dateObj.getMonth()] + " ";
|
||||||
|
dateFormat += dateObj.getDate() + ", ";
|
||||||
|
dateFormat += dateObj.getFullYear();
|
||||||
|
return dateFormat;
|
||||||
|
},
|
||||||
|
sortDate : function (milestone1, milestone2) {
|
||||||
|
|
||||||
|
milestone1.dateTest = (milestone1.due_on) ? milestone1.due_on : milestone1.created_at;
|
||||||
|
milestone2.dateTest = (milestone2.due_on) ? milestone2.due_on : milestone2.created_at;
|
||||||
|
|
||||||
|
var date1 = new Date(milestone1.dateTest );
|
||||||
|
var date2 = new Date(milestone2.dateTest );
|
||||||
|
|
||||||
|
if (date1 < date2) return 1;
|
||||||
|
if (date1 > date2) return -1;
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
sortLabel :function(thisObject,thatObject) {
|
||||||
|
if(!thisObject.labels.length) return 1;
|
||||||
|
if(!thatObject.labels.length) return -1;
|
||||||
|
if (thisObject.labels[0].name > thatObject.labels[0].name){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (thisObject.labels[0].name < thatObject.labels[0].name){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
callApi: function(options){
|
||||||
|
var myoption = $.extend({}, options);
|
||||||
|
if(myoption.repo) delete myoption.repo;
|
||||||
|
return $.ajax({
|
||||||
|
url:this.urls[options.action](options),
|
||||||
|
dataType:respType,
|
||||||
|
data:myoption
|
||||||
|
});
|
||||||
|
},
|
||||||
|
urls : {
|
||||||
|
domainName : "https://api.github.com",
|
||||||
|
milestones : function(){
|
||||||
|
if(!settings.phpApi){
|
||||||
|
return $url = this.domainName+ "/repos/"+settings.username +"/"+ settings.repo +"/milestones";
|
||||||
|
}else{
|
||||||
|
return apiPath;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
issues : function(){
|
||||||
|
if(!settings.phpApi){
|
||||||
|
return $url = this.domainName+"/repos/"+ settings.username +"/"+ settings.repo +"/issues";
|
||||||
|
}else{
|
||||||
|
return apiPath;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
comments : function(options){
|
||||||
|
if(!settings.phpApi){
|
||||||
|
return $url = this.domainName+"/repos/"+ settings.username +"/"+ settings.repo+"/issues/"+ options.issueid +"/comments";
|
||||||
|
}else{
|
||||||
|
return apiPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.each(function(){
|
||||||
|
releases.load(this, settings);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var components = {
|
||||||
|
milestone : function(data){
|
||||||
|
return $('<div data-id-milestone="'+data.number+'" class="milestoneContainer"> \
|
||||||
|
<h3 class="release">'+data.title+'</h3>\
|
||||||
|
<p class="dateRelease">Release Date: '+data.prettyDate+'</p>\
|
||||||
|
<div class="issues"></div>\
|
||||||
|
</div>').data("milestone", data);
|
||||||
|
},
|
||||||
|
issue : function(data){
|
||||||
|
var labels = "",
|
||||||
|
_this = this;
|
||||||
|
|
||||||
|
$.each(data.labels, function(i, label){ labels += _this.label(label); });
|
||||||
|
return $('<div id="issue'+data.number+'" class="issue" >\
|
||||||
|
<div class="issueSmall">\
|
||||||
|
<div class="issueTitle">'+labels+' '+$("<span>").html(data.title).text()+' </div>\
|
||||||
|
</div>\
|
||||||
|
<div style="display:none;" class="issueBig">\
|
||||||
|
<div class="container"></div>\
|
||||||
|
<div style="display:none;" class="comments"></div>\
|
||||||
|
</div>').data("issue", data);
|
||||||
|
},
|
||||||
|
label : function(data){
|
||||||
|
return '<span style="background-color:#'+data.color+';" class="label">'+data.name+'</span>';
|
||||||
|
},
|
||||||
|
bigIssue : function(data, showComment){
|
||||||
|
var commentLink = (data.comments != 0 && showComment) ? '<a data-issue-id="'+data.number+'" href="#" class="btnComments btn">See Comments</a>' : "";
|
||||||
|
|
||||||
|
return $('<div class="avatar-bubble js-comment-container">\
|
||||||
|
<span class="avatar"><img height="48" src="'+data.user.avatar_url+'" width="48"></span>\
|
||||||
|
<div class="bubble">\
|
||||||
|
<div class="comment starting-comment adminable" id="issue-3542089">\
|
||||||
|
<div class="body">\
|
||||||
|
<p class="author">Opened by <a href="'+data.user.url+'">'+data.user.login+'</a>, issue closed on '+data.prettyDate+'</p>\
|
||||||
|
<h2 class="content-title"> '+$("<span>").html(data.title).text()+'</h2>\
|
||||||
|
<div class="formatted-content"> \
|
||||||
|
<div class="content-body markdown-body markdown-format">\
|
||||||
|
'+marked(data.body)+'\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>'+commentLink).data("issue", data);
|
||||||
|
},
|
||||||
|
comment : function(data){
|
||||||
|
return '<div class="avatar-bubble js-comment-container">\
|
||||||
|
<span class="avatar"><img height="48" src="'+data.user.avatar_url+'" width="48"></span>\
|
||||||
|
<div class="bubble">\
|
||||||
|
<div id="issuecomment-4369977" class="comment normal-comment adminable">\
|
||||||
|
<div class="cmeta">\
|
||||||
|
<p class="author">\
|
||||||
|
<span class="icon"></span>\
|
||||||
|
<strong class="author"><a href="'+data.user.url+'">'+data.user.login+'</a></strong>\
|
||||||
|
<em class="action-text">\
|
||||||
|
commented\
|
||||||
|
</em>\
|
||||||
|
</p>\
|
||||||
|
<p class="info">\
|
||||||
|
<em class="date"><time class="js-relative-date">'+data.prettyDate+'</time></em>\
|
||||||
|
</p>\
|
||||||
|
</div>\
|
||||||
|
<div class="body">\
|
||||||
|
<div class="formatted-content">\
|
||||||
|
<div class="content-body markdown-body markdown-format">'+marked(data.body)+'</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(jQuery);
|
||||||
20
javascripts/scale.fix.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
fixScale = function(doc) {
|
||||||
|
|
||||||
|
var addEvent = 'addEventListener',
|
||||||
|
type = 'gesturestart',
|
||||||
|
qsa = 'querySelectorAll',
|
||||||
|
scales = [1, 1],
|
||||||
|
meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : [];
|
||||||
|
|
||||||
|
function fix() {
|
||||||
|
meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1];
|
||||||
|
doc.removeEventListener(type, fix, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((meta = meta[meta.length - 1]) && addEvent in doc) {
|
||||||
|
fix();
|
||||||
|
scales = [.25, 1.6];
|
||||||
|
doc[addEvent](type, fix, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
99
javascripts/script.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
(function($) {
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
// putting lines by the pre blocks
|
||||||
|
$("pre").each(function(){
|
||||||
|
var pre = $(this).text().split("\n");
|
||||||
|
var lines = new Array(pre.length+1);
|
||||||
|
for(var i = 0; i < pre.length; i++) {
|
||||||
|
var wrap = Math.floor(pre[i].split("").length / 70)
|
||||||
|
if (pre[i]==""&&i==pre.length-1) {
|
||||||
|
lines.splice(i, 1);
|
||||||
|
} else {
|
||||||
|
lines[i] = i+1;
|
||||||
|
for(var j = 0; j < wrap; j++) {
|
||||||
|
lines[i] += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(this).before("<pre class='lines'>" + lines.join("\n") + "</pre>");
|
||||||
|
});
|
||||||
|
|
||||||
|
var headings = [];
|
||||||
|
|
||||||
|
var collectHeaders = function(){
|
||||||
|
headings.push({"top":$(this).offset().top - 15,"text":$(this).text()});
|
||||||
|
}
|
||||||
|
|
||||||
|
if($(".markdown-body h1").length > 1) $(".markdown-body h1").each(collectHeaders)
|
||||||
|
else if($(".markdown-body h2").length > 1) $(".markdown-body h2").each(collectHeaders)
|
||||||
|
else if($(".markdown-body h3").length > 1) $(".markdown-body h3").each(collectHeaders)
|
||||||
|
|
||||||
|
$(window).scroll(function(){
|
||||||
|
if(headings.length==0) return true;
|
||||||
|
var scrolltop = $(window).scrollTop() || 0;
|
||||||
|
if(headings[0] && scrolltop < headings[0].top) {
|
||||||
|
$(".current-section").css({"opacity":0,"visibility":"hidden"});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$(".current-section").css({"opacity":1,"visibility":"visible"});
|
||||||
|
for(var i in headings) {
|
||||||
|
if(scrolltop >= headings[i].top) {
|
||||||
|
$(".current-section .name").text(headings[i].text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".current-section a").click(function(){
|
||||||
|
$(window).scrollTop(0);
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var defaultSettings = {
|
||||||
|
milestoneNumber : 10,
|
||||||
|
usePHPapi : true,
|
||||||
|
apiPath : '/',
|
||||||
|
repo : 'rails',
|
||||||
|
username : 'rails'
|
||||||
|
};
|
||||||
|
$.fn.releaseNotes = function(settings){
|
||||||
|
settings = $.extend({}, defaultSettings, settings || {});
|
||||||
|
var apiPath = apiPath."api.php";
|
||||||
|
var respType = (settings.usePHPapi) ? "jsonp" : "json"
|
||||||
|
|
||||||
|
return this.each(function(){
|
||||||
|
releases.load(this, settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
var releases = {
|
||||||
|
|
||||||
|
load: function(){
|
||||||
|
this.callApi({
|
||||||
|
action:"milestones"
|
||||||
|
}).success(function(resp){
|
||||||
|
console.log(resp)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
callApi: function(action){
|
||||||
|
|
||||||
|
return $.ajax({
|
||||||
|
url:this.urls[action](),
|
||||||
|
dataType:respType,
|
||||||
|
data:settings
|
||||||
|
})
|
||||||
|
},
|
||||||
|
urls : {
|
||||||
|
milestones : function(){
|
||||||
|
if(settings.usePHPapi){
|
||||||
|
return $url = "/repos/". $configs["username"] ."/". $configs["repo"] ."/milestones";
|
||||||
|
}else{
|
||||||
|
return apiPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
)(jQuery)
|
||||||
1
params.json
Normal file
46
release.html
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
|
||||||
|
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
|
||||||
|
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
|
||||||
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<title>Release Notes</title>
|
||||||
|
|
||||||
|
<link href="stylesheets/style.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="stylesheets/releasenotes.plugin.css">
|
||||||
|
|
||||||
|
|
||||||
|
<script src="javascripts/libs/jquery-1.7.1.min.js"></script>
|
||||||
|
<script src="javascripts/libs/marked.js"></script>
|
||||||
|
<script src="javascripts/releasenotes.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$("#releaseNotesContainer").releaseNotes({
|
||||||
|
milestonesShown : 10,
|
||||||
|
// If you want to show private repo
|
||||||
|
// You need to add repo credentials in api.php
|
||||||
|
phpApi : false,
|
||||||
|
phpApiPath : '/',
|
||||||
|
showDescription : true,
|
||||||
|
showComments : true,
|
||||||
|
// Used if phpAPI is false
|
||||||
|
repo : 'canal',
|
||||||
|
username : 'alibaba'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="websiteContainer">
|
||||||
|
<div class="containerRelease">
|
||||||
|
<h1>Release Notes</h1>
|
||||||
|
<div id="releaseNotesContainer" role="main"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
69
stylesheets/pygment_trac.css
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
.highlight { background: #ffffff; }
|
||||||
|
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||||
|
.highlight .k { font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { font-weight: bold } /* Operator */
|
||||||
|
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
||||||
|
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||||
|
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||||
|
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
||||||
|
.highlight .go { color: #888888 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||||
|
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kn { font-weight: bold } /* Keyword.Namespace */
|
||||||
|
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #009999 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #d14 } /* Literal.String */
|
||||||
|
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #008080 } /* Name.Constant */
|
||||||
|
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||||
|
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||||
|
.highlight .ow { font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
||||||
|
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||||
|
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||||
|
|
||||||
|
.type-csharp .highlight .k { color: #0000FF }
|
||||||
|
.type-csharp .highlight .kt { color: #0000FF }
|
||||||
|
.type-csharp .highlight .nf { color: #000000; font-weight: normal }
|
||||||
|
.type-csharp .highlight .nc { color: #2B91AF }
|
||||||
|
.type-csharp .highlight .nn { color: #000000 }
|
||||||
|
.type-csharp .highlight .s { color: #A31515 }
|
||||||
|
.type-csharp .highlight .sc { color: #A31515 }
|
||||||
274
stylesheets/releasenotes.plugin.css
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.milestoneContainer{
|
||||||
|
padding-bottom:35px;
|
||||||
|
margin-bottom:10px;
|
||||||
|
}
|
||||||
|
.milestoneContainer.separator{background:url("../images/lineseparator.png") bottom center no-repeat;}
|
||||||
|
.milestoneContainer .cursor:hover{cursor:pointer;}
|
||||||
|
|
||||||
|
h3.release {margin:0 0 2px 0;font-size:18px;}
|
||||||
|
p.dateRelease{margin:0 0 10px 0; font-size:14px;}
|
||||||
|
|
||||||
|
.milestoneContainer .body p{padding:5px 0; margin:0;}
|
||||||
|
.milestoneContainer pre {
|
||||||
|
display: block;
|
||||||
|
padding: 8.5px;
|
||||||
|
margin: 0 0 9px;
|
||||||
|
font-size: 12.025px;
|
||||||
|
line-height: 18px;
|
||||||
|
background-color: whiteSmoke;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
white-space: pre;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
.milestoneContainer code, .milestoneContainer pre {
|
||||||
|
padding: 0 3px 2px;
|
||||||
|
font-family: Menlo,Monaco,"Courier New",monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #333;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* BUTTONS */
|
||||||
|
.milestoneContainer .btn {
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration:none;
|
||||||
|
*display: inline;
|
||||||
|
/* IE7 inline-block hack */
|
||||||
|
|
||||||
|
*zoom: 1;
|
||||||
|
padding: 4px 10px 4px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #333333;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
|
||||||
|
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
|
||||||
|
border-color: #e6e6e6 #e6e6e6 #bfbfbf;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:dximagetransform.microsoft.gradient(enabled=false);
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-bottom-color: #b3b3b3;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
cursor: pointer;
|
||||||
|
*margin-left: .3em;
|
||||||
|
}
|
||||||
|
.milestoneContainer .btn:hover,
|
||||||
|
.milestoneContainer .btn:active{
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
}
|
||||||
|
.milestoneContainer .btn:active,
|
||||||
|
.milestoneContainer .btn.active {
|
||||||
|
background-color: #cccccc \9;
|
||||||
|
}
|
||||||
|
.milestoneContainer .btn:first-child {
|
||||||
|
*margin-left: 0;
|
||||||
|
}
|
||||||
|
.milestoneContainer .btn:hover {
|
||||||
|
color: #333333;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
-webkit-transition: background-position 0.1s linear;
|
||||||
|
-moz-transition: background-position 0.1s linear;
|
||||||
|
-ms-transition: background-position 0.1s linear;
|
||||||
|
-o-transition: background-position 0.1s linear;
|
||||||
|
transition: background-position 0.1s linear;
|
||||||
|
}
|
||||||
|
.milestoneContainer .btn:focus {
|
||||||
|
outline: thin dotted #333;
|
||||||
|
outline: 5px auto -webkit-focus-ring-color;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
.milestoneContainer .btn:active {
|
||||||
|
background-image: none;
|
||||||
|
-webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
-moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
background-color: #d9d9d9 \9;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ISSUE DESCRIPTION */
|
||||||
|
.milestoneContainer .date{
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
.milestoneContainer .cmeta .date {font-size:11px;}
|
||||||
|
.milestoneContainer .issue{
|
||||||
|
padding-bottom: 3px;
|
||||||
|
}
|
||||||
|
.milestoneContainer .issues{
|
||||||
|
color:#555;
|
||||||
|
}
|
||||||
|
.milestoneContainer .issueTitle{
|
||||||
|
line-height:24px;
|
||||||
|
font-size:13px;
|
||||||
|
}
|
||||||
|
.milestoneContainer .label{
|
||||||
|
display:inline-block;
|
||||||
|
font-family: arial;
|
||||||
|
font-weight:normal;
|
||||||
|
line-height: 13px;
|
||||||
|
color: white;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size:12px;
|
||||||
|
color:#fff;
|
||||||
|
text-shadow: 1px 1px 1 #000;
|
||||||
|
padding:3px 4px;
|
||||||
|
border-radius:5px;
|
||||||
|
margin-top: -6px;
|
||||||
|
margin-right:5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.milestoneContainer .btnComments{
|
||||||
|
margin:-8px 0 15px 63px ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.milestoneContainer .hidden{display:none;}
|
||||||
|
.milestoneContainer .content-body{
|
||||||
|
padding-top:10px;
|
||||||
|
margin-top:15px;
|
||||||
|
border-top:1px solid #CACACA;
|
||||||
|
}
|
||||||
|
.milestoneContainer .normal-comment .content-body{
|
||||||
|
padding-top: 0px;
|
||||||
|
margin-top: 0px;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* COMMENTS */
|
||||||
|
|
||||||
|
.milestoneContainer .new-comments .bubble .comment { margin: 0 }
|
||||||
|
.milestoneContainer .view-pull-request .new-comments .bubble .commit-comment { margin-top: 3px }
|
||||||
|
.milestoneContainer .new-comments .bubble .commit-comment.thread-start { margin-top: 0 }
|
||||||
|
.milestoneContainer .bubble .comment-form { margin: 0 }
|
||||||
|
|
||||||
|
.milestoneContainer .avatar-bubble {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding-left: 60px;
|
||||||
|
background: url('../images/bubble-arrow.png') 51px 20px no-repeat;
|
||||||
|
}
|
||||||
|
.milestoneContainer .avatar-bubble>.avatar {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
margin-left: -60px;
|
||||||
|
}
|
||||||
|
.bubble {
|
||||||
|
padding: 3px;
|
||||||
|
background: #eee;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.milestoneContainer .avatar-bubble .form-actions { margin-top: 10px }
|
||||||
|
.milestoneContainer .bubble .file-box { margin-bottom: 0 }
|
||||||
|
|
||||||
|
.milestoneContainer .avatar img { border-radius: 3px }
|
||||||
|
|
||||||
|
.milestoneContainer .starting-comment {
|
||||||
|
margin: 0;
|
||||||
|
background: #fff;
|
||||||
|
padding:0px;
|
||||||
|
border: 1px solid #CACACA;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.milestoneContainer .normal-comment .starting-comment{ padding:10px;}
|
||||||
|
.milestoneContainer .starting-comment .content-title { border-bottom: none }
|
||||||
|
.milestoneContainer .starting-comment h2.content-title {
|
||||||
|
margin: 0 0 -6px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.milestoneContainer .starting-comment .body p.author {
|
||||||
|
margin: 0px 0 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.milestoneContainer .starting-comment p.author a {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.milestoneContainer .new-comments .starting-comment .body {
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.milestoneContainer .comment .cmeta {
|
||||||
|
height: 33px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border-bottom: 1px solid #CCC;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
background-image: -moz-linear-gradient(#F8F8F8,#E1E1E1);
|
||||||
|
background-image: -webkit-linear-gradient(#F8F8F8,#E1E1E1);
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8f8f8',endColorstr='#e1e1e1',GradientType=0)";
|
||||||
|
}
|
||||||
|
.milestoneContainer .comment .cmeta p.author {
|
||||||
|
margin: 0;
|
||||||
|
float: left;
|
||||||
|
max-width: 600px;
|
||||||
|
font-size: 12px;
|
||||||
|
height: 33px;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7);
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.milestoneContainer .comment .cmeta .icon {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: -2px;
|
||||||
|
margin-left: 0px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
background: url('../images/icons.png') 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
.milestoneContainer .comment .cmeta p.author a {
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.milestoneContainer .comment .cmeta p.info {
|
||||||
|
float: right;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 11px;
|
||||||
|
height: 33px;
|
||||||
|
line-height: 33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.milestoneContainer .comment > .body {
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 12px;
|
||||||
|
background: #FBFBFB;
|
||||||
|
}
|
||||||
30
stylesheets/style.css
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
body{
|
||||||
|
background:url(../images/bg.jpg);
|
||||||
|
text-shadow: 1px 1px 0px white;
|
||||||
|
margin: 0;
|
||||||
|
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin: 0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: bold;
|
||||||
|
color: inherit;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 30px;
|
||||||
|
line-height: 36px;
|
||||||
|
padding: 50px 0 20px;
|
||||||
|
}
|
||||||
|
#websiteContainer{
|
||||||
|
background:url(../images/bg2.png) top left no-repeat;
|
||||||
|
height: 529px;
|
||||||
|
}
|
||||||
|
.containerRelease{
|
||||||
|
width:780px;
|
||||||
|
margin-left:230px;
|
||||||
|
}
|
||||||
413
stylesheets/styles.css
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
@import url(https://fonts.googleapis.com/css?family=Arvo:400,700,400italic);
|
||||||
|
|
||||||
|
/* MeyerWeb Reset */
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, embed,
|
||||||
|
figure, figcaption, footer, header, hgroup,
|
||||||
|
menu, nav, output, ruby, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Base text styles */
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding:10px 50px 0 0;
|
||||||
|
font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #232323;
|
||||||
|
background-color: #FBFAF7;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.8em;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
color:#232323;
|
||||||
|
margin:36px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, ul, ol, table, dl {
|
||||||
|
margin:0 0 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
font-family: Arvo, Monaco, serif;
|
||||||
|
line-height:1.3;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2, h3 {
|
||||||
|
display: block;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4, h5, h6 {
|
||||||
|
font-family: Arvo, Monaco, serif;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color:#C30000;
|
||||||
|
font-weight:200;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a small {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight:700;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul li {
|
||||||
|
list-style: inside;
|
||||||
|
padding-left: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol li {
|
||||||
|
list-style: decimal inside;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0 20px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl, dt, dd, dl p {
|
||||||
|
font-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dd {
|
||||||
|
padding-left: 20px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl p {
|
||||||
|
padding-left: 20px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border:0;
|
||||||
|
background:#ccc;
|
||||||
|
height:1px;
|
||||||
|
margin:0 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Images */
|
||||||
|
|
||||||
|
img {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 650px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 10px 0 32px 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
|
||||||
|
code, pre {
|
||||||
|
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
|
||||||
|
color:#000;
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 4px 12px;
|
||||||
|
background: #FDFEFB;
|
||||||
|
border-radius:4px;
|
||||||
|
border:1px solid #D7D8C8;
|
||||||
|
overflow: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
|
||||||
|
table {
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
font-family: 'Arvo', Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 10px;
|
||||||
|
background: #232323;
|
||||||
|
color: #FDFEFB;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 10px;
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Wrapper */
|
||||||
|
.wrapper {
|
||||||
|
width:960px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
|
||||||
|
header {
|
||||||
|
background-color: #171717;
|
||||||
|
color: #FDFDFB;
|
||||||
|
width:170px;
|
||||||
|
float:left;
|
||||||
|
position:fixed;
|
||||||
|
border: 1px solid #000;
|
||||||
|
-webkit-border-top-right-radius: 4px;
|
||||||
|
-webkit-border-bottom-right-radius: 4px;
|
||||||
|
-moz-border-radius-topright: 4px;
|
||||||
|
-moz-border-radius-bottomright: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
padding: 34px 25px 22px 50px;
|
||||||
|
margin: 30px 25px 0 0;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.header {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.header {
|
||||||
|
font-family: Arvo, sans-serif;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.3em;
|
||||||
|
border-bottom: none;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h1.header, a.header, a.name, header a{
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.header {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.name {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style:none;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
list-style-type: none;
|
||||||
|
width:132px;
|
||||||
|
height:15px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
line-height: 1em;
|
||||||
|
padding: 6px 6px 6px 7px;
|
||||||
|
|
||||||
|
background: #AF0011;
|
||||||
|
background: -moz-linear-gradient(top, #AF0011 0%, #820011 100%);
|
||||||
|
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));
|
||||||
|
background: -webkit-linear-gradient(top, #AF0011 0%,#820011 100%);
|
||||||
|
background: -o-linear-gradient(top, #AF0011 0%,#820011 100%);
|
||||||
|
background: -ms-linear-gradient(top, #AF0011 0%,#820011 100%);
|
||||||
|
background: linear-gradient(top, #AF0011 0%,#820011 100%);
|
||||||
|
|
||||||
|
border-radius:4px;
|
||||||
|
border:1px solid #0D0D0D;
|
||||||
|
|
||||||
|
-webkit-box-shadow: inset 0px 1px 1px 0 rgba(233,2,38, 1);
|
||||||
|
box-shadow: inset 0px 1px 1px 0 rgba(233,2,38, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
header li:hover {
|
||||||
|
background: #C3001D;
|
||||||
|
background: -moz-linear-gradient(top, #C3001D 0%, #950119 100%);
|
||||||
|
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));
|
||||||
|
background: -webkit-linear-gradient(top, #C3001D 0%,#950119 100%);
|
||||||
|
background: -o-linear-gradient(top, #C3001D 0%,#950119 100%);
|
||||||
|
background: -ms-linear-gradient(top, #C3001D 0%,#950119 100%);
|
||||||
|
background: linear-gradient(top, #C3001D 0%,#950119 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
a.buttons {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
background: url(../images/arrow-down.png) no-repeat;
|
||||||
|
font-weight: normal;
|
||||||
|
text-shadow: rgba(0, 0, 0, 0.4) 0 -1px 0;
|
||||||
|
padding: 2px 2px 2px 22px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.github {
|
||||||
|
background: url(../images/octocat-small.png) no-repeat 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.buttons:hover {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Section - for main page content */
|
||||||
|
|
||||||
|
section {
|
||||||
|
width:650px;
|
||||||
|
float:right;
|
||||||
|
padding-bottom:50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
width:170px;
|
||||||
|
float:left;
|
||||||
|
position:fixed;
|
||||||
|
bottom:10px;
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print, screen and (max-width: 960px) {
|
||||||
|
|
||||||
|
div.wrapper {
|
||||||
|
width:auto;
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header, section, footer {
|
||||||
|
float:none;
|
||||||
|
position:static;
|
||||||
|
width:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
margin:0 84px 0 50px;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding-right:320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
padding:20px 84px 20px 50px;
|
||||||
|
margin:0 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a small {
|
||||||
|
display:inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
position:absolute;
|
||||||
|
right:130px;
|
||||||
|
top:84px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print, screen and (max-width: 720px) {
|
||||||
|
body {
|
||||||
|
word-wrap:break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding:10px 20px 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
padding:10px 0 10px 20px;
|
||||||
|
margin:0 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
margin: 0 0 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul, header p.view {
|
||||||
|
position:static;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print, screen and (max-width: 480px) {
|
||||||
|
|
||||||
|
header ul li.download {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
margin: 0 0 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a{
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body {
|
||||||
|
padding:0.4in;
|
||||||
|
font-size:12pt;
|
||||||
|
color:#444;
|
||||||
|
}
|
||||||
|
}
|
||||||
581
stylesheets/stylesheet.css
Normal file
@@ -0,0 +1,581 @@
|
|||||||
|
/* http://meyerweb.com/eric/tools/css/reset/
|
||||||
|
v2.0 | 20110126
|
||||||
|
License: none (public domain)
|
||||||
|
*/
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, embed,
|
||||||
|
figure, figcaption, footer, header, hgroup,
|
||||||
|
menu, nav, output, ruby, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
/* HTML5 display-role reset for older browsers */
|
||||||
|
article, aside, details, figcaption, figure,
|
||||||
|
footer, header, hgroup, menu, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
ol, ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
blockquote, q {
|
||||||
|
quotes: none;
|
||||||
|
}
|
||||||
|
blockquote:before, blockquote:after,
|
||||||
|
q:before, q:after {
|
||||||
|
content: '';
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: Arial, Arial, Helvetica, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
background: #D1D1D1;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #63a52a;
|
||||||
|
text-decoration: none;
|
||||||
|
-webkit-transition: color ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #90D355;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
margin: 30px 20px 10px;
|
||||||
|
font-size: 60px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
font-family:Georgia, serif;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 675px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
border: 1px solid #2a2a2a;
|
||||||
|
background: #ddd url(../images/pattern.png);
|
||||||
|
box-shadow: 0 0 5px #b1b1b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.tagline {
|
||||||
|
padding: 20px 20px 0;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 0 20px 90px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar {
|
||||||
|
background: #222;
|
||||||
|
border: 5px solid #444;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 -35px 20px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar .inner {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar .watch-fork iframe {
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
.download-bar .watch-fork iframe.last {
|
||||||
|
border-right: 0 none;
|
||||||
|
padding-right: 0;
|
||||||
|
padding-left: 5px;
|
||||||
|
border-left: 1px solid #fff;
|
||||||
|
}
|
||||||
|
.download-bar .watch-fork {
|
||||||
|
overflow: hidden;
|
||||||
|
float: right;
|
||||||
|
background-color: #eee;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar .blc {
|
||||||
|
border: 10px solid black;
|
||||||
|
border-color: transparent transparent black;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -15px;
|
||||||
|
left: 0;
|
||||||
|
-moz-transform: rotate(45deg);
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar .trc {
|
||||||
|
border: 10px solid black;
|
||||||
|
border-color: black transparent transparent;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: -15px;
|
||||||
|
right: 0;
|
||||||
|
-moz-transform: rotate(45deg);
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar .avatar {
|
||||||
|
border: 1px solid black;
|
||||||
|
display: block;
|
||||||
|
padding: 4px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar .avatar img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar a.code {
|
||||||
|
background: transparent url(../images/code.png) no-repeat 0 2px;
|
||||||
|
padding-left: 35px;
|
||||||
|
margin-top: 8px;
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
text-indent: 0;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
opacity: 1;
|
||||||
|
-moz-opacity: 1;
|
||||||
|
filter:alpha(opacity=1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-section {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 50%;
|
||||||
|
width: 693px;
|
||||||
|
margin-left: -352px;
|
||||||
|
background: #222;
|
||||||
|
border: 5px solid #444;
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
-webkit-transition: opacity ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-section p {
|
||||||
|
padding: 5px 27px;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-section a {
|
||||||
|
float: right;
|
||||||
|
text-indent: -10000px;
|
||||||
|
background: transparent url(../images/top.png) no-repeat 0 0;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
opacity: 0.8;
|
||||||
|
margin-right: 12px;
|
||||||
|
margin-top: 12px;
|
||||||
|
-moz-opacity: 0.8;
|
||||||
|
filter:alpha(opacity=8);
|
||||||
|
-webkit-transition: opacity ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-section a:hover {
|
||||||
|
opacity: 1;
|
||||||
|
-moz-opacity: 1;
|
||||||
|
filter:alpha(opacity=1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-section a.zip {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.zip,
|
||||||
|
a.zip span {
|
||||||
|
background: transparent url(../images/zip.png) no-repeat 0 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 21px;
|
||||||
|
opacity: 0.8;
|
||||||
|
display: inline-block;
|
||||||
|
text-indent: -10000px;
|
||||||
|
-moz-opacity: 0.8;
|
||||||
|
filter:alpha(opacity=8);
|
||||||
|
-webkit-transition: opacity ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.tar,
|
||||||
|
a.tar span {
|
||||||
|
background: transparent url(../images/tar.png) no-repeat 0 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 21px;
|
||||||
|
opacity: 0.8;
|
||||||
|
display: inline-block;
|
||||||
|
text-indent: -10000px;
|
||||||
|
-moz-opacity: 0.8;
|
||||||
|
filter:alpha(opacity=8);
|
||||||
|
-webkit-transition: opacity ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.code {
|
||||||
|
background: transparent url(../images/code.png) no-repeat 0 2px;
|
||||||
|
width: 30px;
|
||||||
|
height: 21px;
|
||||||
|
display: block;
|
||||||
|
opacity: 0.8;
|
||||||
|
display: inline-block;
|
||||||
|
text-indent: -10000px;
|
||||||
|
-moz-opacity: 0.8;
|
||||||
|
filter:alpha(opacity=8);
|
||||||
|
-webkit-transition: opacity ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.zip:hover,
|
||||||
|
a.tar:hover,
|
||||||
|
a.code:hover {
|
||||||
|
opacity: 1;
|
||||||
|
-moz-opacity: 1;
|
||||||
|
filter:alpha(opacity=1);
|
||||||
|
}
|
||||||
|
|
||||||
|
a.download-button {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 3px;
|
||||||
|
display: inline-block;
|
||||||
|
text-indent: 0!important;
|
||||||
|
width: auto;
|
||||||
|
float: right;
|
||||||
|
background: #999; /* for non-css3 browsers */
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#37ADD4', endColorstr='#1B657E'); /* for IE */
|
||||||
|
background: -webkit-gradient(linear, left top, left bottom, from(#37ADD4), to(#1B657E)); /* for webkit browsers */
|
||||||
|
background: -moz-linear-gradient(top, #37ADD4, #1B657E); /* for firefox 3.6+ */
|
||||||
|
height: auto;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.download-button span {
|
||||||
|
background-position: 10px 5px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: 5px 10px;
|
||||||
|
padding-left: 45px;
|
||||||
|
display: inline-block;
|
||||||
|
text-indent: 0!important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
margin-bottom: 60px;
|
||||||
|
padding-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .owner {
|
||||||
|
background: #222;
|
||||||
|
border: 5px solid #444;
|
||||||
|
padding: 5px 15px;
|
||||||
|
margin: -67px -10px 35px;
|
||||||
|
color: #d6d6d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .creds small {
|
||||||
|
float: right;
|
||||||
|
font-size: 10px;
|
||||||
|
text-align: right;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .owner .avatar {
|
||||||
|
background-color: #666;
|
||||||
|
display: block;
|
||||||
|
margin: -19px 10px 0 0;
|
||||||
|
width: 60px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .owner img {
|
||||||
|
display: block;
|
||||||
|
border: 1px solid #2a2a2a;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .owner p {
|
||||||
|
font-family:Georgia, serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .owner p a {
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Markdown */
|
||||||
|
.markdown-body h1,
|
||||||
|
.markdown-body h2,
|
||||||
|
.markdown-body h3,
|
||||||
|
.markdown-body h4,
|
||||||
|
.markdown-body h5,
|
||||||
|
.markdown-body h6,
|
||||||
|
.markdown-body p,
|
||||||
|
.markdown-body pre,
|
||||||
|
.markdown-body ul,
|
||||||
|
.markdown-body ol,
|
||||||
|
.markdown-body dl,
|
||||||
|
.markdown-body table,
|
||||||
|
.markdown-body blockquote {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h1,
|
||||||
|
.markdown-body h2,
|
||||||
|
.markdown-body h3,
|
||||||
|
.markdown-body h4,
|
||||||
|
.markdown-body h5,
|
||||||
|
.markdown-body h6 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #557398;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h4 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h5 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body pre {
|
||||||
|
padding: 10px 70px 10px 0;
|
||||||
|
margin-left: -20px;
|
||||||
|
margin-right: -20px;
|
||||||
|
font-family: 'Monaco', 'Lucida Console', monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 20px;
|
||||||
|
box-shadow: inset 0 0 5px #000;
|
||||||
|
word-wrap: break-word;
|
||||||
|
background-color:#3b3b3b;
|
||||||
|
color: #d6d6d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body pre.lines {
|
||||||
|
font-size: 12px;
|
||||||
|
margin:0 10px 0 -20px;
|
||||||
|
padding: 10px;
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
text-align: right;
|
||||||
|
box-shadow: none;
|
||||||
|
background-color:#2a2a2a;
|
||||||
|
color: #d6d6d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body ul,
|
||||||
|
.markdown-body ol {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body ul {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body li,
|
||||||
|
.markdown-body li p,
|
||||||
|
.markdown-body dd,
|
||||||
|
.markdown-body dd p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body li pre,
|
||||||
|
.markdown-body li pre.lines,
|
||||||
|
.markdown-body dd pre,
|
||||||
|
.markdown-body dd pre.lines {
|
||||||
|
margin-left: -35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body dd {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body table {
|
||||||
|
width: 673px;
|
||||||
|
margin-left: -20px;
|
||||||
|
margin-right: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body tbody {
|
||||||
|
border-top: 2px solid #557398;
|
||||||
|
border-bottom: 2px solid #557398;
|
||||||
|
background-color: #EBEFF4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body table td * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body td {
|
||||||
|
border-right: 1px solid #557398;
|
||||||
|
border-bottom: 1px solid #557398;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body td:first-child,
|
||||||
|
.markdown-body th:first-child {
|
||||||
|
width: 30%;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body td:last-child {
|
||||||
|
border-right: 0 none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body th {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: left;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body tt {
|
||||||
|
background-color:#3b3b3b;
|
||||||
|
color: #d6d6d6;
|
||||||
|
padding: 2px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body blockquote {
|
||||||
|
font-style: italic;
|
||||||
|
font-family:Georgia, serif;
|
||||||
|
font-size: 17px;
|
||||||
|
border-top: 3px solid #333;
|
||||||
|
border-bottom: 3px solid #333;
|
||||||
|
padding: 10px 20px;
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body blockquote:before {
|
||||||
|
font-style: italic;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 90px;
|
||||||
|
height: 90px;
|
||||||
|
margin-left: -60px;
|
||||||
|
margin-top: -25px;
|
||||||
|
content: "‟";
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body img {
|
||||||
|
max-width: 100%;
|
||||||
|
@include box-sizing(border-box);
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight { background: #ffffff; }
|
||||||
|
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||||
|
.highlight .k { font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { font-weight: bold } /* Operator */
|
||||||
|
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
||||||
|
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||||
|
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||||
|
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
||||||
|
.highlight .go { color: #888888 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||||
|
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kn { font-weight: bold } /* Keyword.Namespace */
|
||||||
|
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #009999 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #d14 } /* Literal.String */
|
||||||
|
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #008080 } /* Name.Constant */
|
||||||
|
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||||
|
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||||
|
.highlight .ow { font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
||||||
|
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||||
|
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||||