!1 合并 octotree/master 最新代码,解决冲突

Merge pull request !1 from liu/new_version
This commit is contained in:
liu 2018-03-09 20:37:31 +08:00 committed by inu1255
parent 130db7e943
commit 56e7a2e8a7
44 changed files with 3410 additions and 1024 deletions

View File

@ -1,3 +1,30 @@
### v2.4.3
* Fix issue branch path not encoded in file navigation
### v2.4.2
* Fix issue download icon not shown upon hover
### v2.4.1
* Support file icons
### v2.3.3
* Handle local storage error
### v2.3.2
* Improve file navigation speed in pull requests
### v2.3.1
* Fix bug PR mode doesn't work with lazy loading
* Fix bug sidebar width is not stable in Firefox
### v2.3.0
* Support PR viewing mode
* Handle reserved chars in URLs
### v2.2.0
* Support BitBucket (experimental)
* Fix minor bugs
### v2.1.0 ### v2.1.0
* Remove GitLab support * Remove GitLab support
* Improve GitHub styling * Improve GitHub styling

View File

@ -1,20 +1,30 @@
[![OpenCollective](https://opencollective.com/octotree/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/octotree/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/octotree/sponsors/badge.svg)](#sponsors)
## GitCodeTree ## GitCodeTree
fork from [https://github.com/buunguyen/octotree](https://github.com/buunguyen/octotree) fork from [https://github.com/buunguyen/octotree](https://github.com/buunguyen/octotree)
### 二次开发 ## 安装
### 从预先构建的包安装(适用于所有浏览器)
**鉴于国内墙的原因,你可以通过下载已经构建好的包来安装**
预先构建的包可以从 [https://gitee.com/oschina/GitCodeTree/tree/master/dist](https://gitee.com/oschina/GitCodeTree/tree/master/dist) 下载。出于安全原因,请不要从其它地方下载。
__注意__: Firefox 43 + 需要签名。因此您需要从Mozilla商店安装GitCodeTree。出于某种原因,如果你想安装预先构建的包,请参考 [disable sign-check](https://github.com/buunguyen/octotree/issues/220#issuecomment-166012724)。
### 在 Chrome, Firefox 和 Opera 上安装
* 从 [Chrome Web Store](https://chrome.google.com/webstore/detail/gitcodetree/inaaldjpdbkaodlmdcplgpoibohcmmlj)[Mozilla Add-ons Store](https://addons.mozilla.org/zh-CN/firefox/addon/GitCodeTree/) or [Opera Add-ons Store](https://addons.opera.com/en/extensions/details/gitcodetree/) 安装GitCodeTree
* 导航到任何Gitee、GitHub库(或者刷新这个页面作为一个例子)
* 代码树将显示在页面左边
### 在 Safari 上安装
GitCodeTree在Safari gallery中不可用所以您必须使用预先构建的包 或者 从源代码构建一个。
* 下载 [Safari 预先构建的包](https://gitee.com/oschina/GitCodeTree/blob/master/dist/safari.safariextz?raw=true)
* 双击或者拖拽到Safari窗口
* 将项目clone到本地
* 在`src/adapters/`中为你想要支持的网站添加一个类(可复制`src/adapters/github.js`并修改)
* 根据情况实现 [`_getTree`](https://gitee.com/inu1255/GitCodeTree/blob/master/src/adapters/github.js#L149-154) 或 `_get` 方法,用于获取项目树
* 实现 [`updateLayout`](https://gitee.com/inu1255/GitCodeTree/blob/master/src/adapters/github.js#L65-73) 方法,用于修改页面布局
* 实现 [`selectFile`](https://gitee.com/inu1255/GitCodeTree/blob/master/src/adapters/github.js#L135-138) 指定pjax替换的html元素,用于不刷新切换文件
* 在 [`src/octotree.js`](https://gitee.com/inu1255/GitCodeTree/blob/master/src/octotree.js#L30)中添加你修改好的类
* 在 `src/config/` 插件配置文件中添加你想要支持的网站
* __chrome中调试__: 使用`gulp chrome`命令,打开[chrome://extensions/](chrome://extensions/),点击`加载已解压的扩展程度`,选择`src/tmp/chrome`
* __打包__: 使用 `gulp dist` 命令打包
## 介绍 ## 介绍
@ -28,44 +38,41 @@ fork from [https://github.com/buunguyen/octotree](https://github.com/buunguyen/o
![GitCodeTree on GitHub](docs/chrome-github.png) ![GitCodeTree on GitHub](docs/chrome-github.png)
### 在 Chrome, Firefox 和 Opera 上安装 ### 二次开发
* 从 [Chrome Web Store](https://chrome.google.com/webstore/detail/gitcodetree/inaaldjpdbkaodlmdcplgpoibohcmmlj), [Mozilla Add-ons Store](https://addons.mozilla.org/zh-CN/firefox/addon/GitCodeTree/) or [Opera Add-ons Store](https://addons.opera.com/zh-cn/extensions/details/gitcodetree/?display=en) 安装GitCodeTree
* 导航到任何Gitee、GitHub库(或者刷新这个页面作为一个例子)
* 代码树将显示在页面左边
### 在 Safari 上安装 * 将项目clone到本地
* 在`src/adapters/`中为你想要支持的网站添加一个类(可复制`src/adapters/github.js`并修改)
* 根据情况实现 [`_getTree`](https//gitee.com/inu1255/GitCodeTree/blob/master/src/adapters/github.js#L149-154) 或 `_get` 方法,用于获取项目树
* 实现 [`updateLayout`](https//gitee.com/inu1255/GitCodeTree/blob/master/src/adapters/github.js#L65-73) 方法,用于修改页面布局
* 实现 [`selectFile`](https//gitee.com/inu1255/GitCodeTree/blob/master/src/adapters/github.js#L135-138) 指定pjax替换的html元素用于不刷新切换文件
* 在 [`src/octotree.js`](https//gitee.com/inu1255/GitCodeTree/blob/master/src/octotree.js#L30)中添加你修改好的类
* 在 `src/config/` 插件配置文件中添加你想要支持的网站
* __chrome中调试__: 使用`gulp chrome`命令,打开[chrome://extensions/](chrome://extensions/),点击`加载已解压的扩展程度`,选择`src/tmp/chrome`
* __打包__: 使用 `gulp dist` 命令打包
GitCodeTree在Safari gallery中不可用所以,您必须使用预先构建的包 或者 从源代码构建一个。
* 下载 [Safari 预先构建的包](https://gitee.com/inu1255/GitCodeTree/blob/master/dist/safari.safariextz?raw=true)
* 双击或者拖拽到Safari窗口
### 从预先构建的包安装(所有浏览器)
预先构建的包可以从 [这里](https://gitee.com/inu1255/GitCodeTree/tree/master/dist) 下载. 出于安全原因,请不要从其它地方下载.
__注意__: Firefox 43 + 需要签名。因此您需要从Mozilla商店安装GitCodeTree。出于某种原因,如果你想安装预先构建的包, 请参考 [disable sign-check](https://github.com/buunguyen/octotree/issues/220#issuecomment-166012724).
## 设置 ## 设置
### Access Token ### Access Token
__注意__: GitCodeTree 访问令牌在浏览器本地存储并不会上传到任何地方。如果你想验证,查看源代码,开始 [请参考这里](https://gitee.com/inu1255/GitCodeTree/blob/master/src/view.options.js#L77). __注意__: GitCodeTree 访问令牌在浏览器本地存储并不会上传到任何地方。如果你想验证,查看源代码,开始 [请参考这里](https//gitee.com/inu1255/GitCodeTree/blob/master/src/view.options.js#L77).
#### GitHub #### GitHub
GitCodeTree 使用 [GitHub API](https://developer.github.com/v3/) 检索代码树。默认情况下,它使未经身份验证的请求到GitHub API。然而,有两种情况时必须经过身份验证的请求: GitCodeTree 使用 [GitHub API](https://developer.github.com/v3/) 检索代码树。默认情况下它使未经身份验证的请求到GitHub API。然而有两种情况时必须经过身份验证的请求:
* 你访问一个私人存储库 * 你访问一个私人存储库
* 你超过 [请求频率限制限制](https://developer.github.com/v3/#rate-limiting) * 你超过 [请求频率限制限制](https://developer.github.com/v3/#rate-limiting)
当这种情况发生时,GitCodeTree会询问你 [GitHub 私人 access token](https://help.github.com/articles/creating-an-access-token-for-command-line-use). 如果你没有, [点此创建](https://github.com/settings/tokens/new), 然后复制粘贴到文本框中。注意,至少要允许"public_repo","repo" (如果你需要访问私人仓库). 当这种情况发生时GitCodeTree会询问你 [GitHub 私人 access token](https://help.github.com/articles/creating-an-access-token-for-command-line-use). 如果你没有[点此创建](https://github.com/settings/tokens/new) 然后复制粘贴到文本框中。注意,至少要允许"public_repo""repo" (如果你需要访问私人仓库).
![Settings](docs/settings.jpg) ![Settings](docs/settings.jpg)
### 其它 ### 其它
* __热键__: GitCodeTree 使用 [keymaster](https://github.com/madrobby/keymaster) 注册热键。查看 [支持的按键](https://github.com/madrobby/keymaster#supported-keys). * __热键__: GitCodeTree 使用 [keymaster](https://github.com/madrobby/keymaster) 注册热键。查看 [支持的按键](https://github.com/madrobby/keymaster#supported-keys).
* __记得栏可见性__: 如果勾选此项,基于其可见性显示或隐藏GitCodeTree. * __记得栏可见性__: 如果勾选此项基于其可见性显示或隐藏GitCodeTree.
* __在非代码页__: 如果勾选此项,让GitCodeTree等非代码页的问题和请求. * __在非代码页__: 如果勾选此项让GitCodeTree等非代码页的问题和请求.
* __一次加载整个树__: (仅支持github) 如果勾选此项,进入项目页面时GitCodeTree将加载整个项目树。如果您经常访问非常大的项目为了避免长时间加载,请勿勾选此项. * __一次加载整个树__: (仅支持github) 如果勾选此项进入项目页面时GitCodeTree将加载整个项目树。如果您经常访问非常大的项目为了避免长时间加载请勿勾选此项.
## Credits ## Credits
* [@crashbell](https://github.com/crashbell) for helping with GitLab and others * [@crashbell](https://github.com/crashbell) for helping with GitLab and others

27
chrome_test_key.pem Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA7pVSB0UiadYCxCjf8zngckEBVtOASXjxdJKVlTtbBxApg873
0wujcqSZRQrs39m4rV/C0qoqWAnGpfYL7ACqrsZn/FSFfdiGFU9wxQnbPbNIm3zy
xVWuD2sHbp7UtAwIZknQxjkwHV3qoPTRGoXkQ6brLH/khi6B7Ps7y2xURyoCyDmb
f2XjhCSbVRGhsPSZpfekVz4WGiLDMZV0av6d1RuXoXJXjb1sKuDF1xwTUEc+Q8BL
eY3cfzuIvo5KoyB2F0x1mzJrg8KBcTbtXZSJ8PqQlIHeJfiv/NEYHSNy4qpnhp/5
IbsvuOr3XpXPlcd4GUsYswsNrLWgTvedtyuhMwIDAQABAoIBAFT9WFVCqXmuRRn/
vZd1fKD2yzVU7pQ9wzXVqfeZR1oCxecwaVQDB1ylifvwYmVzt7f7LvnAqIjoIp2o
QqL1sdfE0fIvYcZsxYb935wxYKpgHXNWVV06omDXrbQYXIku6CcYEIksghlUBWsF
CyA5phD7ezdE7/Fky9/Rt4FFu9gFTRi2KlrQc5oE7kXbSk84IUKKgnJaiEWTHpRm
n4EFeq7NhQrHuEs/EUV9M4jreP3WqrUE3UwVS0jmxLbVzNbahjv9WuU9vCq8pbHZ
pLZC0RmLBcyxL0KFZJbsU0ZjEg7i0Wlp4N4L415/dCUUm+hVo7ZxycnyZ8OgJXzk
dnY8hBECgYEA9zffVrDE82T09DMBLtgaiiPIUsu1nLe59OKvtg6khxTqyVac1Bd0
KE1a7tHJ9V/AAv7AmJD9i287/R/xwHEd/4SfOX7wzHPiZAzTT4f2wHFcHM4j9jK+
OA5S6uOoZJPrhdtUSdVdqrOQBgYExsSG242IDdP11mHsZA1l2Nc1U30CgYEA9w7s
mjIOBJmkiqh2QBJDIGNUnLygMlOzTbt24jjE5VZT5aU/OxnrhsrgVnXQxOhO0bKG
1XuxJ3qxFKYEvMLOA6vKybvig2bjdywIqagBURf40KI2vOcjJMm0Y0bJ+wJDRoFO
P2Kux7sLTe69zn4d+2V51ZqiXePosa9bNkANhm8CgYBo7l0spaEjEiHqmM+Su4Ug
RynbAr4WQ+F5MNKV+scY0ucJCGtOlpnmFVdYcNFBBiAw5UKIP1pu2Yrj2LA7F4g9
EWSn+dppXXKlNtBmPHaenj8TtueKs2UL1ACb1H+AGUzppvuyzw6PyuGBvQI//+Ch
xgQOon4BPdUhbpJhJI9s3QKBgQCLAImcg/chHXTXUssdZ2j/KwPrH7GePzuNy6Cq
zTfytKyFc4Ds9rtuXmz0GFt6vh3CnAiCypI03TIOpQ3bSltw81IoSJ68QcJPRaYm
FlGPV8Z1VB8qD33Vb+sfRC/WG0LQw2XMAfDGjXVhxqZiLNEfpctzpAoge19rwXa3
QjiZ3wKBgQCZ3qAbCWKf5GHoBfs+MpsfbAmzkenkbEGa/JZO3TJLkz34b+aB2irj
zblnQT3o3ljtXroF/Mgw4dF+fozAWi4NjDLAlX/tImwB/jBF02xukaa51tDbchqv
gtU/3j05xaH5H46zSD9sE7qR1PSudI3etvKxFQcAYT5c/qVeKe5S/Q==
-----END RSA PRIVATE KEY-----

BIN
dist/chrome.crx vendored

Binary file not shown.

BIN
dist/chrome.zip vendored

Binary file not shown.

BIN
dist/firefox.xpi vendored

Binary file not shown.

BIN
dist/firefox.zip vendored Normal file

Binary file not shown.

BIN
dist/opera.nex vendored

Binary file not shown.

BIN
docs/chrome-github.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 KiB

BIN
docs/opera-github.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,11 +1,11 @@
import gulp from 'gulp' import gulp from 'gulp'
import fs from 'fs' import fs from 'fs'
import os from 'os'
import path from 'path' import path from 'path'
import { merge } from 'event-stream' import { merge } from 'event-stream'
import map from 'map-stream' import map from 'map-stream'
import { spawn } from 'child_process' import { spawn } from 'child_process'
const $ = require('gulp-load-plugins')() const $ = require('gulp-load-plugins')()
const version = require('./package.json').version
// Tasks // Tasks
gulp.task('clean', () => { gulp.task('clean', () => {
@ -17,11 +17,11 @@ gulp.task('build', (cb) => {
}) })
gulp.task('default', ['build'], () => { gulp.task('default', ['build'], () => {
gulp.watch(['./libs/**/*', './src/**/*'], ['default']) gulp.watch(['./libs/**/*', './src/**/*', './package.json'], ['default'])
}) })
gulp.task('dist', ['build'], (cb) => { gulp.task('dist', ['build'], (cb) => {
$.runSequence('firefox:xpi', 'chrome:zip', 'chrome:crx', 'opera:nex', cb) $.runSequence('firefox:zip', 'chrome:zip', 'chrome:crx', 'opera:nex', cb)
}) })
gulp.task('test', ['build'], (cb) => { gulp.task('test', ['build'], (cb) => {
@ -59,20 +59,20 @@ gulp.task('lib:ondemand', (cb) => {
// Chrome // Chrome
gulp.task('chrome:template', () => { gulp.task('chrome:template', () => {
return buildTemplate({ CHROME: true }) return buildTemplate({SUPPORT_FILE_ICONS: true, SUPPORT_GHE: true})
}) })
gulp.task('chrome:js', ['chrome:template', 'lib:ondemand'], () => { gulp.task('chrome:js', ['chrome:template', 'lib:ondemand'], () => {
return buildJs(['./src/config/chrome/overrides.js'], { CHROME: true }) return buildJs(['./src/config/chrome/overrides.js'], {SUPPORT_FILE_ICONS: true, SUPPORT_GHE: true})
}) })
gulp.task('chrome', ['chrome:js'], () => { gulp.task('chrome', ['chrome:js'], () => {
return merge( return merge(
pipe('./icons/**/*', './tmp/chrome/icons'), pipe('./icons/**/*', './tmp/chrome/icons'),
pipe('./fonts/**/*', './tmp/chrome/fonts'),
pipe(['./libs/**/*', '!./libs/ondemand{,/**}', './tmp/octotree.*', './tmp/ondemand.js'], './tmp/chrome/'), pipe(['./libs/**/*', '!./libs/ondemand{,/**}', './tmp/octotree.*', './tmp/ondemand.js'], './tmp/chrome/'),
pipe('./libs/file-icons.css', $.replace('../fonts', 'chrome-extension://__MSG_@@extension_id__/fonts'), './tmp/chrome/'),
pipe('./src/config/chrome/background.js', $.babel(), './tmp/chrome/'), pipe('./src/config/chrome/background.js', $.babel(), './tmp/chrome/'),
pipe('./src/config/chrome/manifest.json', $.replace('$VERSION', version), './tmp/chrome/') pipe('./src/config/chrome/manifest.json', $.replace('$VERSION', getVersion()), './tmp/chrome/')
) )
}) })
@ -80,15 +80,19 @@ gulp.task('chrome:zip', () => {
return pipe('./tmp/chrome/**/*', $.zip('chrome.zip'), './dist') return pipe('./tmp/chrome/**/*', $.zip('chrome.zip'), './dist')
}) })
gulp.task('chrome:_crx', (cb) => { gulp.task('chrome:crx', () => {
$.run('"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"' + // This will package the crx using a private key.
' --pack-extension=' + path.join(__dirname, './tmp/chrome') + // For the convenience of people who want to build locally without having to
' --pack-extension-key=' + path.join(process.env.HOME, '.ssh/chrome.pem') // manage their own Chrome key, this code will use the bundled test key if
).exec(cb) // a real key is not found in ~/.ssh.
}) const real = path.join(os.homedir() + '.ssh/chrome.pem')
const test = './chrome_test_key.pem'
const privateKey = fs.existsSync(real) ? fs.readFileSync(real) : fs.readFileSync(test)
gulp.task('chrome:crx', ['chrome:_crx'], () => { return pipe('./tmp/chrome', $.crxPack({
return pipe('./tmp/chrome.crx', './dist') privateKey: privateKey,
filename: 'chrome.crx'
}), './dist')
}) })
// Opera // Opera
@ -102,33 +106,34 @@ gulp.task('opera:nex', () => {
// Firefox // Firefox
gulp.task('firefox:template', () => { gulp.task('firefox:template', () => {
return buildTemplate({ FIREFOX: true }) return buildTemplate({SUPPORT_FILE_ICONS: true})
}) })
gulp.task('firefox:js', ['firefox:template', 'lib:ondemand'], () => { gulp.task('firefox:js', ['firefox:template', 'lib:ondemand'], () => {
return buildJs([], { FIREFOX: true }) return buildJs([], {SUPPORT_FILE_ICONS: true})
}) })
gulp.task('firefox', ['firefox:js'], () => { gulp.task('firefox', ['firefox:js'], () => {
return merge( return merge(
pipe('./icons/**/*', './tmp/firefox/data/icons'), pipe('./icons/**/*', './tmp/firefox/icons'),
pipe(['./libs/**/*', '!./libs/ondemand{,/**}', './tmp/octotree.*', './tmp/ondemand.js'], './tmp/firefox/data'), pipe(['./libs/**/*', '!./libs/ondemand{,/**}', './tmp/octotree.*', './tmp/ondemand.js'], './tmp/firefox'),
pipe('./src/config/firefox/firefox.js', $.babel(), './tmp/firefox/lib'), pipe('./libs/file-icons.css', $.replace('../fonts', 'moz-extension://__MSG_@@extension_id__/fonts'), './tmp/firefox/'),
pipe('./src/config/firefox/package.json', $.replace('$VERSION', version), './tmp/firefox') pipe('./src/config/firefox/background.js', $.babel(), './tmp/firefox/'),
pipe('./src/config/firefox/manifest.json', $.replace('$VERSION', getVersion()), './tmp/firefox')
) )
}) })
gulp.task('firefox:xpi', (cb) => { gulp.task('firefox:zip', () => {
$.run('cd ./tmp/firefox && ../../node_modules/.bin/jpm xpi && mkdir -p ../../dist && mv GitCodeTree.xpi ../../dist/firefox.xpi').exec(cb) return pipe('./tmp/firefox/**/*', $.zip('firefox.zip'), './dist')
}) })
// Safari // Safari
gulp.task('safari:template', () => { gulp.task('safari:template', () => {
return buildTemplate({ SAFARI: true }) return buildTemplate({})
}) })
gulp.task('safari:js', ['safari:template', 'lib:ondemand'], () => { gulp.task('safari:js', ['safari:template', 'lib:ondemand'], () => {
return buildJs([], { SAFARI: true }) return buildJs([], {})
}) })
gulp.task('safari', ['safari:js'], () => { gulp.task('safari', ['safari:js'], () => {
@ -138,7 +143,7 @@ gulp.task('safari', ['safari:js'], () => {
['./libs/**/*', '!./libs/ondemand{,/**}', './tmp/octotree.*', './tmp/ondemand.js'], ['./libs/**/*', '!./libs/ondemand{,/**}', './tmp/octotree.*', './tmp/ondemand.js'],
'./tmp/safari/octotree.safariextension/' './tmp/safari/octotree.safariextension/'
), ),
pipe('./src/config/safari/Info.plist', $.replace('$VERSION', version), './tmp/safari/octotree.safariextension') pipe('./src/config/safari/Info.plist', $.replace('$VERSION', getVersion()), './tmp/safari/octotree.safariextension')
) )
}) })
@ -173,6 +178,7 @@ function buildJs(overrides, ctx) {
'./tmp/template.js', './tmp/template.js',
'./src/constants.js', './src/constants.js',
'./src/adapters/adapter.js', './src/adapters/adapter.js',
'./src/adapters/pjax.js',
'./src/adapters/bitbucket.js', './src/adapters/bitbucket.js',
'./src/adapters/github.js', './src/adapters/github.js',
'./src/adapters/oschina.js', './src/adapters/oschina.js',
@ -207,3 +213,8 @@ function buildTemplate(ctx) {
'./tmp' './tmp'
) )
} }
function getVersion() {
delete require.cache[require.resolve('./package.json')]
return require('./package.json').version
}

642
libs/file-icons.css Normal file
View File

@ -0,0 +1,642 @@
/*
| File Icons
| @link https://github.com/file-icons
| @author Daniel Brooker https://github.com/DanBrooker
*/
/* ----------------------------[ Colors ]---------------------------------- */
/*============================================================================*
PALETTE
Base16 colours from https://github.com/chriskempson/base16
/*============================================================================*/
.light-red:before {
color: #c97071;
}
.medium-red:before {
color: #ac4142;
}
.dark-red:before {
color: #742c2d;
}
.light-green:before {
color: #a6ba7b;
}
.medium-green:before {
color: #90a959;
}
.dark-green:before {
color: #66783e;
}
.light-yellow:before {
color: #fae0bc;
}
.medium-yellow:before {
color: #ee9e2e;
}
.dark-yellow:before {
color: #d88511;
}
.light-blue:before {
color: #6098b0;
}
.medium-blue:before {
color: #6a9fb5;
}
.dark-blue:before {
color: #46788d;
}
.light-maroon:before {
color: #be7953;
}
.medium-maroon:before {
color: #8f5536;
}
.dark-maroon:before {
color: #573421;
}
.light-purple:before {
color: #c7a4c0;
}
.medium-purple:before {
color: #aa759f;
}
.dark-purple:before {
color: #825078;
}
.light-orange:before {
color: #d99762;
}
.medium-orange:before {
color: #d28445;
}
.dark-orange:before {
color: #a35f27;
}
.light-cyan:before {
color: #6bb0a4;
}
.medium-cyan:before {
color: #75b5aa;
}
.dark-cyan:before {
color: #4d9085;
}
.light-pink:before {
color: #ff4ddb;
}
.medium-pink:before {
color: #ff00cc;
}
.dark-pink:before {
color: #b3008f;
}
.theme-colour-check {
background: #ffffff;
}
/* ----------------------------[ Fonts ]---------------------------------- */
@font-face {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
src: url("../fonts/fontawesome.woff2");
}
@font-face {
font-family: Mfizz;
src: url("../fonts/mfixx.woff2");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: Devicons;
src: url("../fonts/devopicons.woff2");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: file-icons;
src: url("../fonts/file-icons.woff2");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: octicons;
src: url("../fonts/octicons.woff2");
font-weight: normal;
font-style: normal;
}
/* ----------------------------[ Icons ]---------------------------------- */
.icon:before{
font-weight: normal;
font-style: normal;
text-align: center;
width: 16px;
line-height: 1;
position: relative;
display: inline-block;
-webkit-font-smoothing: antialiased;
}
/*============================================================================*
Octicons
https://github.com/github/octicons
/*============================================================================*/
.binary-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f094"; }
.book-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f007"; }
.brew-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f069"; font-size: 15px; left: 1px; }
.checklist-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f076"; font-size: 17px; left: 1px; }
.code-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f05f"; }
.database-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f096"; }
.gear-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f02f"; }
.git-commit-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f01f"; }
.git-merge-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f023"; }
.github-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f00a"; }
.graph-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f043"; }
.image-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f012"; }
.key-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f049"; }
.link-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f0b0"; }
.markdown-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f0c9"; }
.package-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f0c4"; }
.ruby-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f047"; }
.secret-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f08c"; }
.squirrel-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f0b2"; font-size: 15px; }
.text-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f011"; }
.zip-icon:before { font-family: octicons; font-size: 16px; top: 1px; content: "\f013"; }
/*============================================================================*
FontAwesome
http://fortawesome.github.io/Font-Awesome/cheatsheet
/*============================================================================*/
.android-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f17b"; font-size: 16px; top: 1px; }
.at-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f1fa"; font-size: 15px; top: 1px; }
.audio-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f028"; font-size: 15px; top: 1px; }
.bullhorn-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f0a1"; font-size: 16px; top: 2px; }
.calc-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f1ec"; font-size: 14px; }
.coffee-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f0f4"; font-size: 14px; top: 1px; }
.css3-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f13c"; top: 0; }
.circle-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f111"; font-size: 16px; top: 1px; }
.earth-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f0ac"; font-size: 15px; }
.gears-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f085"; font-size: 15px; }
.html5-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f13b"; font-size: 15px; top: 1px; }
.mobile-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f10b"; font-size: 20px; top: 2px; }
.moon-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f186"; font-size: 16px; top: 1px; }
.music-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f001"; font-size: 15px; }
.print-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f02f"; font-size: 15px; top: 2px; }
.recycle-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f1b8"; font-size: 15px; top: 2px; }
.rss-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f143"; font-size: 16px; top: 2px; }
.smarty-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f0eb"; font-size: 15px; }
.sourcemap-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f279"; font-size: 14px; }
.sun-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f185"; font-size: 14px; -webkit-font-smoothing: subpixel-antialiased; }
.toc-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f03a"; font-size: 15px; top: 2px; }
.twig-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f1bb"; font-size: 14px; }
.pdf-icon:before { font-family: FontAwesome; font-size: 13px; content: "\f1c1"; font-size: 14px; }
/*============================================================================*
Mfizz
http://mfizz.com/oss/font-mfizz
/*============================================================================*/
.apache-icon:before { font-family: Mfizz; font-size: 14px; content: "\f102"; top: 3px; font-size: 15px; }
.archlinux-icon:before { font-family: Mfizz; font-size: 14px; content: "A"; top: 1px; font-size: 15px; }
.c-icon:before { font-family: Mfizz; font-size: 14px; content: "\f106"; top: 1px; font-size: 13px; }
.cpp-icon:before { font-family: Mfizz; font-size: 14px; content: "\f10b"; top: 1px; }
.csharp-icon:before { font-family: Mfizz; font-size: 14px; content: "\f10c"; top: 1px; }
.debian-icon:before { font-family: Mfizz; font-size: 14px; content: "\f111"; top: 1px; }
.elixir-icon:before { font-family: Mfizz; font-size: 14px; content: "\f113"; top: 1px; }
.gnome-icon:before { font-family: Mfizz; font-size: 14px; content: "\f119"; top: 1px; }
.haskell-icon:before { font-family: Mfizz; font-size: 14px; content: "\f121"; top: 2px; font-size: 16px; }
.java-icon:before { font-family: Mfizz; font-size: 14px; content: "\f126"; top: 2px; font-size: 16px; }
.js-icon:before { font-family: Mfizz; font-size: 14px; content: "\f129"; top: 1px; font-size: 14px; }
.msql-icon:before { font-family: Mfizz; font-size: 14px; content: "\f136"; top: 2px; font-size: 15px; text-shadow: 0 0 0; }
.objc-icon:before { font-family: Mfizz; font-size: 14px; content: "\f13e"; top: 2px; font-size: 16px; }
.osx-icon:before { font-family: Mfizz; font-size: 14px; content: "\f141"; top: 1px; }
.perl-icon:before { font-family: Mfizz; font-size: 14px; content: "\f142"; top: 1px; }
.python-icon:before { font-family: Mfizz; font-size: 14px; content: "\f14c"; top: 1px; }
.red-hat-icon:before { font-family: Mfizz; font-size: 14px; content: "\f14e"; top: 2px; }
.scala-icon:before { font-family: Mfizz; font-size: 14px; content: "\f154"; top: 1px; }
.sql-icon:before { font-family: Mfizz; font-size: 14px; content: "\f10e"; top: 1px; }
.svg-icon:before { font-family: Mfizz; font-size: 14px; content: "\f15c"; top: 1px; }
.tt-icon:before { font-family: Mfizz; font-size: 14px; content: "TT"; }
.x11-icon:before { font-family: Mfizz; font-size: 14px; content: "\f16e"; top: 1px; font-size: 13px; }
/*============================================================================*
Devicons
http://vorillaz.github.io/devicons
/*============================================================================*/
.angular-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e653"; }
.appcelerator-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6ab"; }
.appstore-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e613"; }
.asp-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e67f"; }
.atom-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e664"; -webkit-font-smoothing: subpixel-antialiased; }
.backbone-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e652"; }
.bootstrap-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e647"; font-size: 15px; top: 2px; }
.bower-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e64d"; text-shadow: 0 0 0; }
.chrome-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e643"; }
.clojure-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e668"; -webkit-font-smoothing: subpixel-antialiased; }
.compass-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e661"; font-size: 14px; top: 2px; }
.dart-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e698"; font-size: 15px; top: 2px; }
.dlang-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6af"; }
.dojo-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e61c"; font-size: 16px; top: 4px; transform: scale(1.2); -webkit-font-smoothing: subpixel-antialiased; }
.dropbox-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e607"; }
.eclipse-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e69e"; }
.erlang-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6b1"; }
.extjs-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e68e"; }
.fsharp-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6a7"; left: 1px; top: 2px; }
.git-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e602"; font-size: 15px; top: 2px; }
.heroku-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e67b"; }
.jquery-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e650"; font-size: 15px; top: 2px; }
.jqueryui-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e654"; font-size: 15px; top: 2px; }
.laravel-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e63f"; -webkit-font-smoothing: subpixel-antialiased; }
.materialize-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6b6"; transform: scale(1.2); -webkit-font-smoothing: subpixel-antialiased; }
.modernizr-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e620"; }
.mootools-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e68f"; text-shadow: 0 0 0; }
.node-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e618"; }
.pod-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e669"; font-size: 15px; top: 2px; }
.prolog-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6a1"; }
.rails-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e63b"; }
.raphael-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e65f"; font-size: 15px; }
.requirejs-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e670"; }
.rust-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6a8"; }
.sass-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e64b"; }
.sencha-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e68c"; }
.snapsvg-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e65e"; }
.swift-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e655"; left: -1px; }
.travis-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e67e"; font-size: 15px; top: 2px; }
.uikit-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e673"; font-size: 15px; top: 2px; }
.unity3d-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e621"; }
.vim-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e6c5"; }
.vs-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e60c"; font-size: 14px; top: 2px; }
.windows-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e60f"; font-size: 14px; top: 2px; }
.yeoman-icon:before { font-family: Devicons; font-size: 16px; top: 3px; content: "\e67a"; }
/*============================================================================*
Custom file icons
See https://github.com/file-icons/source/#adding-new-icons
/*============================================================================*/
._1c-icon:before { font-family: file-icons; font-size: 15px; content: "\a5ea"; top: 3px; font-size: 16px; }
._1c-alt-icon:before { font-family: file-icons; font-size: 15px; content: "\ea28"; top: 3px; font-size: 16px; }
.abap-icon:before { font-family: file-icons; font-size: 15px; content: "\e92b"; top: 2px; }
.access-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ea"; top: 2px; }
.ada-icon:before { font-family: file-icons; font-size: 15px; content: "\e90b"; top: 3px; font-size: 17px; }
.ae-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f3"; top: 2px; }
.ahk-icon:before { font-family: file-icons; font-size: 15px; content: "\e932"; top: 2px; }
.ai-icon:before { font-family: file-icons; font-size: 15px; content: "\e6b4"; top: 2px; }
.alloy-icon:before { font-family: file-icons; font-size: 15px; content: "\e935"; top: 2px; }
.alpine-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ff"; top: 2px; font-size: 16px; }
.ampl-icon:before { font-family: file-icons; font-size: 15px; content: "\e94e"; top: 3px; font-size: 16px; left: 1px; }
.amx-icon:before { font-family: file-icons; font-size: 15px; content: "\e99b"; top: 3px; font-size: 16px; }
.ant-icon:before { font-family: file-icons; font-size: 15px; content: "\e93e"; top: 4px; font-size: 18px; transform: scale(1.1); }
.antlr-icon:before { font-family: file-icons; font-size: 15px; content: "\e92c"; top: 3px; }
.api-icon:before { font-family: file-icons; font-size: 15px; content: "\e92d"; top: 2px; }
.apl-icon:before { font-family: file-icons; font-size: 15px; content: "\234b"; top: 2px; }
.apple-icon:before { font-family: file-icons; font-size: 15px; content: "\e925"; top: 1px; }
.appveyor-icon:before { font-family: file-icons; font-size: 15px; content: "\e923"; top: 2px; }
.arc-icon:before { font-family: file-icons; font-size: 15px; content: "\e92f"; top: 2px; }
.arduino-icon:before { font-family: file-icons; font-size: 15px; content: "\e930"; top: 3px; font-size: 16px; }
.arttext-icon:before { font-family: file-icons; font-size: 15px; content: "\24d0"; top: 2px; }
.as-icon:before { font-family: file-icons; font-size: 15px; content: "\e92e"; top: 1px; font-size: 14px; }
.asciidoc-icon:before { font-family: file-icons; font-size: 15px; content: "\e918"; top: 1px; font-size: 14px; }
.ats-icon:before { font-family: file-icons; font-size: 15px; content: "\e934"; top: 2px; }
.audacity-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f9"; top: 2px; }
.augeas-icon:before { font-family: file-icons; font-size: 15px; content: "\e931"; top: 2px; }
.autoit-icon:before { font-family: file-icons; font-size: 15px; content: "\e933"; top: 2px; font-size: 16px; }
.babel-icon:before { font-family: file-icons; font-size: 15px; content: "\e91f"; top: 2px; left: 1px; }
.bibtex-icon:before { font-family: file-icons; font-size: 15px; content: "\e601"; top: 2px; font-size: 16px; -webkit-font-smoothing: subpixel-antialiased; }
.blender-icon:before { font-family: file-icons; font-size: 15px; content: "\e9fa"; top: 2px; }
.bluespec-icon:before { font-family: file-icons; font-size: 15px; content: "\e93c"; top: 1px; font-size: 13px; left: 1px; }
.boo-icon:before { font-family: file-icons; font-size: 15px; content: "\e939"; top: 2px; }
.boot-icon:before { font-family: file-icons; font-size: 15px; content: "\f103"; top: 2px; font-size: 16px; }
.brain-icon:before { font-family: file-icons; font-size: 15px; content: "\e93a"; top: 2px; }
.brakeman-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d6"; top: 2px; }
.bro-icon:before { font-family: file-icons; font-size: 15px; content: "\e93b"; top: 3px; font-size: 16px; }
.broccoli-icon:before { font-family: file-icons; font-size: 15px; content: "\e922"; top: 1px; font-size: 14px; }
.byond-icon:before { font-family: file-icons; font-size: 15px; content: "\e962"; top: 2px; }
.cabal-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c2"; top: 2px; }
.cake-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e3"; top: 2px; }
.cakefile-icon:before { font-family: file-icons; font-size: 15px; content: "\e924"; top: 2px; }
.cakephp-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d3"; top: 1px; font-size: 14px; }
.cc-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d5"; top: 2px; font-size: 16px; }
.ceylon-icon:before { font-family: file-icons; font-size: 15px; content: "\e94f"; top: 2px; }
.cf-icon:before { font-family: file-icons; font-size: 15px; content: "\e929"; top: 2px; }
.chai-icon:before { font-family: file-icons; font-size: 15px; content: "c"; top: 3px; font-size: 16px; }
.chapel-icon:before { font-family: file-icons; font-size: 15px; content: "\e950"; top: 2px; }
.chartjs-icon:before { font-family: file-icons; font-size: 15px; content: "\ea0b"; top: 2px; }
.chuck-icon:before { font-family: file-icons; font-size: 15px; content: "\e943"; top: 2px; }
.circleci-icon:before { font-family: file-icons; font-size: 15px; content: "\ea12"; top: 2px; font-size: 14px; }
.cirru-icon:before { font-family: file-icons; font-size: 15px; content: "\e951"; top: 2px; text-shadow: 0 0 0; }
.cl-icon:before { font-family: file-icons; font-size: 15px; content: "\e972"; top: 2px; text-shadow: 0 0 0; }
.clarion-icon:before { font-family: file-icons; font-size: 15px; content: "\e952"; top: 1px; font-size: 14px; left: 1px; }
.clean-icon:before { font-family: file-icons; font-size: 15px; content: "\e95b"; top: 2px; font-size: 16px; }
.click-icon:before { font-family: file-icons; font-size: 15px; content: "\e95c"; top: 2px; }
.clips-icon:before { font-family: file-icons; font-size: 15px; content: "\e940"; top: 3px; font-size: 18px; }
.cljs-icon:before { font-family: file-icons; font-size: 15px; content: "\f104"; top: 2px; }
.cmake-icon:before { font-family: file-icons; font-size: 15px; content: "\e93f"; top: 1px; font-size: 14px; }
.codecov-icon:before { font-family: file-icons; font-size: 15px; content: "\2602"; top: 2px; }
.composer-icon:before { font-family: file-icons; font-size: 15px; content: "\e683"; top: 3px; font-size: 17px; }
.config-icon:before { font-family: file-icons; font-size: 15px; content: "\f07c"; top: 2px; font-size: 14px; }
.cordova-icon:before { font-family: file-icons; font-size: 15px; content: "\ea11"; top: 2px; }
.coq-icon:before { font-family: file-icons; font-size: 15px; content: "\e95f"; top: 2px; font-size: 16px; left: 1px; }
.cp-icon:before { font-family: file-icons; font-size: 15px; content: "\e942"; top: 3px; font-size: 17px; }
.creole-icon:before { font-family: file-icons; font-size: 15px; content: "\e95e"; top: 2px; }
.crystal-icon:before { font-family: file-icons; font-size: 15px; content: "\e902"; top: 2px; left: 1px; }
.csound-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f0"; top: 2px; }
.csscript-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e2"; top: 2px; }
.cucumber-icon:before { font-family: file-icons; font-size: 15px; content: "\f02b"; top: 3px; }
.cython-icon:before { font-family: file-icons; font-size: 15px; content: "\e963"; top: 2px; }
.d3-icon:before { font-family: file-icons; font-size: 15px; content: "\ea10"; top: 2px; }
.darcs-icon:before { font-family: file-icons; font-size: 15px; content: "\e964"; top: 2px; }
.dashboard-icon:before { font-family: file-icons; font-size: 15px; content: "\f07d"; top: 2px; font-size: 13px; }
.dbase-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f1"; top: 2px; }
.default-icon:before { font-family: file-icons; font-size: 15px; content: "\1f5cc";top: 2px; font-size: 14px; }
.diff-icon:before { font-family: file-icons; font-size: 15px; content: "\e960"; top: 2px; }
.docker-icon:before { font-family: file-icons; font-size: 15px; content: "\f106"; top: 3px; font-size: 18px; }
.doxygen-icon:before { font-family: file-icons; font-size: 15px; content: "\e928"; top: 1px; font-size: 13px; }
.doge-icon:before { font-family: file-icons; font-size: 15px; content: "\e946"; top: 2px; }
.dyalog-icon:before { font-family: file-icons; font-size: 15px; content: "\e90c"; top: 1px; font-size: 14px; left: 1px; }
.dylib-icon:before { font-family: file-icons; font-size: 15px; content: "\ea15"; top: 2px; }
.e-icon:before { font-family: file-icons; font-size: 15px; content: "E"; top: 1px; font-size: 14px; }
.eagle-icon:before { font-family: file-icons; font-size: 15px; content: "\e965"; top: 2px; }
.ec-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c9"; top: 2px; }
.ecere-icon:before { font-family: file-icons; font-size: 15px; content: "\e966"; top: 3px; font-size: 16px; }
.editorconfig-icon:before { font-family: file-icons; font-size: 15px; content: "\ea1b"; top: 3px; }
.eiffel-icon:before { font-family: file-icons; font-size: 15px; content: "\e967"; top: 2px; font-size: 16px; }
.electron-icon:before { font-family: file-icons; font-size: 15px; content: "\ea27"; top: 3px; font-size: 16px; text-shadow: 0 0 0; }
.elm-icon:before { font-family: file-icons; font-size: 15px; content: "\f102"; top: 2px; }
.em-icon:before { font-family: file-icons; font-size: 15px; content: "\e968"; top: 3px; font-size: 16px; }
.ember-icon:before { font-family: file-icons; font-size: 15px; content: "\e61b"; top: 2px; font-size: 14px; }
.emacs-icon:before { font-family: file-icons; font-size: 15px; content: "\e926"; top: 2px; }
.eq-icon:before { font-family: file-icons; font-size: 15px; content: "\ea0a"; top: 5px; }
.eslint-icon:before { font-family: file-icons; font-size: 15px; content: "\ea0f"; top: 3px; font-size: 16px; }
.excel-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ee"; top: 2px; }
.fabfile-icon:before { font-family: file-icons; font-size: 15px; content: "\e94b"; top: 2px; font-size: 16px; }
.factor-icon:before { font-family: file-icons; font-size: 15px; content: "\e96a"; top: 3px; font-size: 18px; left: -2px; transform: scale(1.2); }
.fancy-icon:before { font-family: file-icons; font-size: 15px; content: "\e96b"; top: 2px; font-size: 16px; }
.fantom-icon:before { font-family: file-icons; font-size: 15px; content: "\e96f"; top: 2px; left: 1px; }
.fbx-icon:before { font-family: file-icons; font-size: 15px; content: "\e9fc"; top: 2px; }
.ff-icon:before { font-family: file-icons; font-size: 15px; content: "\fb00"; top: 3px; }
.finder-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e9"; top: 3px; font-size: 16px; }
.flow-icon:before { font-family: file-icons; font-size: 15px; content: "\e921"; top: 1px; }
.flux-icon:before { font-family: file-icons; font-size: 15px; content: "\e969"; top: 2px; }
.font-icon:before { font-family: file-icons; font-size: 15px; content: "\e90f"; top: 1px; font-size: 14px; left: 1px; }
.fortran-icon:before { font-family: file-icons; font-size: 15px; content: "\e90a"; top: 1px; font-size: 14px; left: 1px; }
.freemarker-icon:before { font-family: file-icons; font-size: 15px; content: "\e970"; top: 2px; font-size: 16px; left: 1px; }
.frege-icon:before { font-family: file-icons; font-size: 15px; content: "\e96e"; top: 2px; font-size: 16px; left: 1px; }
.fuelux-icon:before { font-family: file-icons; font-size: 15px; content: "\ea09"; top: 3px; font-size: 16px; left: 2px; transform: scale(1.15); text-shadow: 0 0 0; }
.gams-icon:before { font-family: file-icons; font-size: 15px; content: "\e973"; top: 2px; left: 1px; }
.gap-icon:before { font-family: file-icons; font-size: 15px; content: "\e971"; top: 3px; font-size: 16px; left: 1px; }
.gdb-icon:before { font-family: file-icons; font-size: 15px; content: "\ea08"; top: 3px; font-size: 16px; transform: scale(1.15); text-shadow: 0 0 0; }
.genshi-icon:before { font-family: file-icons; font-size: 15px; content: "\e976"; top: 3px; }
.gentoo-icon:before { font-family: file-icons; font-size: 15px; content: "\e96d"; top: 1px; font-size: 14px; left: 1px; }
.gf-icon:before { font-family: file-icons; font-size: 15px; content: "\e978"; top: 2px; }
.glade-icon:before { font-family: file-icons; font-size: 15px; content: "\e938"; top: 2px; }
.glyphs-icon:before { font-family: file-icons; font-size: 15px; content: "G"; top: 3px; }
.gml-icon:before { font-family: file-icons; font-size: 15px; content: "\e975"; top: 3px; font-size: 16px; }
.gn-icon:before { font-family: file-icons; font-size: 15px; content: "\ea25"; top: 2px; }
.gnu-icon:before { font-family: file-icons; font-size: 15px; content: "\e679"; top: 2px; font-size: 16px; text-shadow: 0 0 0; }
.go-icon:before { font-family: file-icons; font-size: 15px; content: "\e624"; top: 3px; }
.godot-icon:before { font-family: file-icons; font-size: 15px; content: "\e974"; top: 2px; }
.golo-icon:before { font-family: file-icons; font-size: 15px; content: "\e979"; top: 2px; }
.gosu-icon:before { font-family: file-icons; font-size: 15px; content: "\e97a"; top: 2px; }
.gradle-icon:before { font-family: file-icons; font-size: 15px; content: "\e903"; top: 3px; font-size: 16px; left: 1px; }
.graphql-icon:before { font-family: file-icons; font-size: 15px; content: "\e97c"; top: 2px; }
.graphviz-icon:before { font-family: file-icons; font-size: 15px; content: "\e97d"; top: 4px; font-size: 17px; left: 1px; }
.groovy-icon:before { font-family: file-icons; font-size: 15px; content: "\e904"; top: 4px; font-size: 17px; left: -1px; }
.grunt-icon:before { font-family: file-icons; font-size: 15px; content: "\e611"; top: 1px; font-size: 14px; }
.gulp-icon:before { font-family: file-icons; font-size: 15px; content: "\e610"; top: 2px; font-size: 16px; }
.hack-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ce"; top: 2px; }
.haml-icon:before { font-family: file-icons; font-size: 15px; content: "\f15b"; top: 2px; }
.harbour-icon:before { font-family: file-icons; font-size: 15px; content: "\e97b"; top: 2px; font-size: 16px; text-shadow: 0 0 0; }
.hashicorp-icon:before { font-family: file-icons; font-size: 15px; content: "\e97e"; top: 2px; }
.haxe-icon:before { font-family: file-icons; font-size: 15px; content: "\e907"; top: 2px; }
.hy-icon:before { font-family: file-icons; font-size: 15px; content: "\e97f"; top: 2px; }
.idl-icon:before { font-family: file-icons; font-size: 15px; content: "\e947"; top: 3px; font-size: 18px; }
.idris-icon:before { font-family: file-icons; font-size: 15px; content: "\e983"; top: 2px; font-size: 16px; -webkit-font-smoothing: subpixel-antialiased; }
.igorpro-icon:before { font-family: file-icons; font-size: 15px; content: "\e980"; top: 2px; font-size: 16px; -webkit-font-smoothing: subpixel-antialiased; }
.indesign-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f4"; top: 2px; }
.inform7-icon:before { font-family: file-icons; font-size: 15px; content: "\e984"; top: 2px; font-size: 16px; text-shadow: 0 0 0; }
.inno-icon:before { font-family: file-icons; font-size: 15px; content: "\e985"; top: 2px; }
.io-icon:before { font-family: file-icons; font-size: 15px; content: "\e981"; top: 1px; font-size: 13px; -webkit-font-smoothing: subpixel-antialiased; }
.ioke-icon:before { font-family: file-icons; font-size: 15px; content: "\e982"; top: 2px; }
.ionic-icon:before { font-family: file-icons; font-size: 15px; content: "\f14b"; top: 2px; }
.isabelle-icon:before { font-family: file-icons; font-size: 15px; content: "\e945"; top: 2px; font-size: 16px; }
.j-icon:before { font-family: file-icons; font-size: 15px; content: "\e937"; top: 1px; font-size: 13px; }
.jade-icon:before { font-family: file-icons; font-size: 15px; content: "\e90d"; top: 1px; font-size: 14px; }
.jake-icon:before { font-family: file-icons; font-size: 15px; content: "\e948"; top: 3px; font-size: 16px; }
.jenkins-icon:before { font-family: file-icons; font-size: 15px; content: "\e667"; top: 3px; font-size: 18px; text-shadow: 0 0 0; }
.jinja-icon:before { font-family: file-icons; font-size: 15px; content: "\e944"; top: 2px; }
.jsonld-icon:before { font-family: file-icons; font-size: 15px; content: "\e958"; top: 3px; font-size: 17px; }
.jsx-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e6"; top: 1px; font-size: 14px; }
.julia-icon:before { font-family: file-icons; font-size: 15px; content: "\26ec"; top: 1px; font-size: 14px; }
.jupyter-icon:before { font-family: file-icons; font-size: 15px; content: "\e987"; top: 3px; font-size: 16px; }
.karma-icon:before { font-family: file-icons; font-size: 15px; content: "\e9cd"; top: 2px; }
.keynote-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e5"; top: 2px; }
.khronos-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f8"; top: 2px; }
.kivy-icon:before { font-family: file-icons; font-size: 15px; content: "\e901"; top: 2px; }
.knockout-icon:before { font-family: file-icons; font-size: 15px; content: "\4B"; top: 2px; }
.kotlin-icon:before { font-family: file-icons; font-size: 15px; content: "\e989"; top: 1px; font-size: 14px; }
.krl-icon:before { font-family: file-icons; font-size: 15px; content: "\e988"; top: 1px; font-size: 14px; }
.labview-icon:before { font-family: file-icons; font-size: 15px; content: "\e98a"; top: 2px; font-size: 16px; }
.lasso-icon:before { font-family: file-icons; font-size: 15px; content: "\e98c"; top: 2px; left: 1px; }
.leaflet-icon:before { font-family: file-icons; font-size: 15px; content: "\ea07"; top: 2px; }
.lean-icon:before { font-family: file-icons; font-size: 15px; content: "L"; top: 1px; font-size: 13px; }
.lein-icon:before { font-family: file-icons; font-size: 15px; content: "\f105"; top: 3px; font-size: 16px; text-shadow: 0 0 0; transform: scale(1.15); }
.lfe-icon:before { font-family: file-icons; font-size: 15px; content: "\e94c"; top: 2px; font-size: 16px; }
.lightwave-icon:before { font-family: file-icons; font-size: 15px; content: "\e9fb"; top: 2px; }
.lisp-icon:before { font-family: file-icons; font-size: 15px; content: "\e908"; top: 3px; font-size: 17px; }
.llvm-icon:before { font-family: file-icons; font-size: 15px; content: "\e91d"; top: 3px; font-size: 17px; }
.logtalk-icon:before { font-family: file-icons; font-size: 15px; content: "\e98d"; top: 2px; text-shadow: 0 0 0; }
.lookml-icon:before { font-family: file-icons; font-size: 15px; content: "\e98e"; top: 2px; font-size: 16px; text-shadow: 0 0 0; }
.ls-icon:before { font-family: file-icons; font-size: 15px; content: "\e914"; top: 2px; font-size: 14px; }
.lsl-icon:before { font-family: file-icons; font-size: 15px; content: "\e98b"; top: 1px; }
.lua-icon:before { font-family: file-icons; font-size: 15px; content: "\e91b"; top: 2px; font-size: 14px; }
.mako-icon:before { font-family: file-icons; font-size: 15px; content: "\e98f"; top: 4px; font-size: 16px; }
.mapbox-icon:before { font-family: file-icons; font-size: 15px; content: "\e941"; top: 1px; font-size: 13px; }
.marko-icon:before { font-family: file-icons; font-size: 15px; content: "\e920"; top: 4px; font-size: 18px; left: -1px; transform: scale(1.05); }
.mathematica-icon:before { font-family: file-icons; font-size: 15px; content: "\e990"; top: 2px; font-size: 16px; }
.mathjax-icon:before { font-family: file-icons; font-size: 15px; content: "\ea06"; top: 2px; }
.matlab-icon:before { font-family: file-icons; font-size: 15px; content: "\e991"; top: 2px; }
.max-icon:before { font-family: file-icons; font-size: 15px; content: "\e993"; top: 2px; }
.maxscript-icon:before { font-family: file-icons; font-size: 15px; content: "\e900"; top: 2px; }
.maya-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f6"; top: 2px; font-size: 16px; }
.manpage-icon:before { font-family: file-icons; font-size: 15px; content: "\e936"; top: 3px; }
.mediawiki-icon:before { font-family: file-icons; font-size: 15px; content: "\e954"; top: 2px; font-size: 16px; }
.mercury-icon:before { font-family: file-icons; font-size: 15px; content: "\e994"; top: 3px; font-size: 16px; transform: scale(1.2); }
.metal-icon:before { font-family: file-icons; font-size: 15px; content: "M"; top: 1px; left: 1px; }
.meteor-icon:before { font-family: file-icons; font-size: 15px; content: "\e6a5"; top: 1px; }
.minecraft-icon:before { font-family: file-icons; font-size: 15px; content: "\e9dc"; top: 2px; }
.mirah-icon:before { font-family: file-icons; font-size: 15px; content: "\e995"; top: 2px; }
.mocha-icon:before { font-family: file-icons; font-size: 15px; content: "\26fe"; top: 2px; font-size: 17px; }
.model-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e8"; top: 2px; font-size: 16px; }
.modula2-icon:before { font-family: file-icons; font-size: 15px; content: "\e996"; top: 2px; }
.monkey-icon:before { font-family: file-icons; font-size: 15px; content: "\e997"; top: 3px; font-size: 18px; left: -1px; }
.mruby-icon:before { font-family: file-icons; font-size: 15px; content: "\ea18"; top: 2px; }
.mupad-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ca"; top: 3px; font-size: 16px; }
.mustache-icon:before { font-family: file-icons; font-size: 15px; content: "\e60f"; top: 2px; font-size: 16px; }
.nant-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e1"; top: 3px; transform: scale(1.2); }
.neko-icon:before { font-family: file-icons; font-size: 15px; content: "\ea05"; top: 2px; }
.netlogo-icon:before { font-family: file-icons; font-size: 15px; content: "\e99c"; top: 2px; left: 1px; }
.newrelic-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d7"; top: 2px; }
.nginx-icon:before { font-family: file-icons; font-size: 15px; content:"\f146b"; top: 2px; }
.nib-icon:before { font-family: file-icons; font-size: 15px; content: "\2712"; top: 2px; }
.nimrod-icon:before { font-family: file-icons; font-size: 15px; content: "\e998"; top: 2px; }
.nit-icon:before { font-family: file-icons; font-size: 15px; content: "\e999"; top: 2px; }
.nix-icon:before { font-family: file-icons; font-size: 15px; content: "\e99a"; top: 3px; font-size: 16px; }
.nmap-icon:before { font-family: file-icons; font-size: 15px; content: "\e94d"; top: 3px; font-size: 16px; transform: scale(1.1); }
.nodemon-icon:before { font-family: file-icons; font-size: 15px; content: "\ea26"; top: 2px; }
.normalize-icon:before { font-family: file-icons; font-size: 15px; content: "\ea04"; top: 3px; font-size: 16px; }
.npm-icon:before { font-family: file-icons; font-size: 15px; content: "\e91c"; top: 3px; font-size: 17px; }
.nsis-icon:before { font-family: file-icons; font-size: 15px; content: "\ea1e"; top: 3px; font-size: 16px; }
.numpy-icon:before { font-family: file-icons; font-size: 15px; content: "\e99d"; top: 2px; font-size: 14px; }
.nuget-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d9"; top: 2px; }
.nunjucks-icon:before { font-family: file-icons; font-size: 15px; content: "\e953"; top: 2px; font-size: 16px; }
.nvidia-icon:before { font-family: file-icons; font-size: 15px; content: "\e95d"; top: 2px; }
.objj-icon:before { font-family: file-icons; font-size: 15px; content: "\e99e"; top: 2px; }
.ocaml-icon:before { font-family: file-icons; font-size: 15px; content: "\e91a"; top: 1px; font-size: 14px; }
.onenote-icon:before { font-family: file-icons; font-size: 15px; content: "\e9eb"; top: 2px; }
.ooc-icon:before { font-family: file-icons; font-size: 15px; content: "\e9cb"; top: 2px; }
.opa-icon:before { font-family: file-icons; font-size: 15px; content: "\2601"; top: 2px; }
.opencl-icon:before { font-family: file-icons; font-size: 15px; content: "\e99f"; top: 2px; font-size: 16px; }
.openoffice-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e4"; top: 2px; }
.org-icon:before { font-family: file-icons; font-size: 15px; content: "\e917"; top: 1px; font-size: 14px; left: 1px; }
.owl-icon:before { font-family: file-icons; font-size: 15px; content: "\e957"; top: 2px; }
.ox-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a1"; top: 3px; font-size: 16px; text-shadow: 0 0 0; }
.oxygene-icon:before { font-family: file-icons; font-size: 15px; content: "\e9bf"; top: 2px; }
.oz-icon:before { font-family: file-icons; font-size: 15px; content: "\e9be"; top: 2px; }
.pan-icon:before { font-family: file-icons; font-size: 15px; content: "\e9bd"; top: 2px; }
.papyrus-icon:before { font-family: file-icons; font-size: 15px; content: "\e9bc"; top: 2px; }
.parrot-icon:before { font-family: file-icons; font-size: 15px; content: "\e9bb"; top: 3px; font-size: 16px; }
.pascal-icon:before { font-family: file-icons; font-size: 15px; content: "\e92a"; top: 2px; }
.patch-icon:before { font-family: file-icons; font-size: 15px; content: "\e961"; top: 2px; }
.pawn-icon:before { font-family: file-icons; font-size: 15px; content: "\265f"; top: 1px; font-size: 14px; }
.perl6-icon:before { font-family: file-icons; font-size: 15px; content: "\e96c"; top: 2px; }
.phalcon-icon:before { font-family: file-icons; font-size: 15px; content: "\e94a"; top: 2px; }
.php-icon:before { font-family: file-icons; font-size: 15px; content: "\f147"; top: 1px; font-size: 14px; left: 1px; }
.pickle-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c4"; top: 2px; }
.pike-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b9"; top: 4px; font-size: 16px; -webkit-font-smoothing: subpixel-antialiased; transform: scale(1.15); }
.pogo-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b8"; top: 3px; font-size: 14px; -webkit-font-smoothing: subpixel-antialiased; }
.pony-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b7"; top: 3px; font-size: 16px; }
.pointwise-icon:before { font-family: file-icons; font-size: 15px; content: "\e977"; top: 2px; }
.postcss-icon:before { font-family: file-icons; font-size: 15px; content: "\e910"; top: 2px; font-size: 14px; }
.postscript-icon:before { font-family: file-icons; font-size: 15px; content: "\e955"; top: 2px; left: 1px; }
.povray-icon:before { font-family: file-icons; font-size: 15px; content: "P"; top: 2px; left: 1px; }
.powerbuilder-icon:before { font-family: file-icons; font-size: 15px; content: "\ea14"; }
.powerpoint-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ec"; top: 2px; }
.powershell-icon:before { font-family: file-icons; font-size: 15px; content: "\e9da"; top: 2px; font-size: 16px; }
.premiere-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f5"; top: 2px; }
.processing-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a0"; top: 2px; }
.progress-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c0"; top: 2px; font-size: 16px; transform: scale(1.2); }
.propeller-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b5"; top: 3px; font-size: 16px; }
.protractor-icon:before { font-family: file-icons; font-size: 15px; content: "\e9de"; top: 3px; }
.psd-icon:before { font-family: file-icons; font-size: 15px; content: "\e6b8"; top: 2px; }
.pug-icon:before { font-family: file-icons; font-size: 15px; content: "\ea13"; top: 3px; font-size: 16px; }
.pug-alt-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d0"; top: 3px; font-size: 16px; }
.puppet-icon:before { font-family: file-icons; font-size: 15px; content: "\f0c3"; top: 2px; left: 1px; }
.purebasic-icon:before { font-family: file-icons; font-size: 15px; content: "\01b5"; top: 2px; }
.purescript-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b2"; top: 3px; }
.r-icon:before { font-family: file-icons; font-size: 15px; content: "\e905"; top: 3px; font-size: 17px; }
.racket-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b1"; top: 2px; left: 1px; }
.raml-icon:before { font-family: file-icons; font-size: 15px; content: "\e913"; top: 1px; font-size: 14px; }
.rascal-icon:before { font-family: file-icons; font-size: 15px; content: "\ea24"; top: 2px; }
.rdoc-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b0"; top: 2px; left: 1px; }
.react-icon:before { font-family: file-icons; font-size: 15px; content: "\f100"; top: 2px; }
.rebol-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ae"; top: 1px; font-size: 13px; }
.reason-icon:before { font-family: file-icons; font-size: 15px; content: "\ea1d"; top: 3px; }
.red-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ad"; top: 3px; font-size: 16px; }
.regex-icon:before { font-family: file-icons; font-size: 15px; content: "*"; top: 1px; font-size: 12px; left: 1px; }
.rexx-icon:before { font-family: file-icons; font-size: 15px; content: "\ea16"; top: 2px; font-size: 14px; left: 1px; }
.riot-icon:before { font-family: file-icons; font-size: 15px; content: "\e919"; top: 4px; font-size: 18px; }
.robot-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ac"; top: 2px; font-size: 14px; }
.rollup-icon:before { font-family: file-icons; font-size: 15px; content: "\ea20"; top: 2px; }
.rst-icon:before { font-family: file-icons; font-size: 15px; content: "\e9cc"; top: 3px; font-size: 16px; }
.sage-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ab"; top: 3px; font-size: 16px; -webkit-font-smoothing: subpixel-antialiased; }
.saltstack-icon:before { font-family: file-icons; font-size: 15px; content: "\e915"; top: 2px; font-size: 14px; }
.sas-icon:before { font-family: file-icons; font-size: 15px; content: "\e95a"; top: 2px; }
.sbt-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d2"; top: 2px; font-size: 14px; }
.scd-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a2"; top: 2px; }
.scad-icon:before { font-family: file-icons; font-size: 15px; content: "\e911"; top: 2px; font-size: 14px; }
.scheme-icon:before { font-family: file-icons; font-size: 15px; content: "\03bb"; top: 2px; }
.scilab-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a9"; top: 3px; font-size: 18px; left: -1px; -webkit-font-smoothing: subpixel-antialiased; }
.scrutinizer-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d4"; top: 2px; font-size: 14px; }
.self-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a8"; top: 3px; font-size: 16px; text-shadow: 0 0 0; transform: scale(1.2); }
.sf-icon:before { font-family: file-icons; font-size: 15px; content: "\e9db"; top: 2px; }
.shen-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a7"; top: 2px; font-size: 16px; }
.shopify-icon:before { font-family: file-icons; font-size: 15px; content: "\e9cf"; top: 2px; }
.shuriken-icon:before { font-family: file-icons; font-size: 15px; content: "\272b"; top: 2px; font-size: 14px; }
.sigils-icon:before { font-family: file-icons; font-size: 15px; content: "\1f764";top: 3px; font-size: 16px; text-shadow: 0 0 0; }
.silverstripe-icon:before { font-family: file-icons; font-size: 15px; content: "\e800"; top: 2px; }
.sketch-icon:before { font-family: file-icons; font-size: 15px; content: "\e927"; top: 2px; }
.slash-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a6"; top: 2px; }
.snyk-icon:before { font-family: file-icons; font-size: 15px; content: "\ea1c"; top: 2px; font-size: 16px; }
.sparql-icon:before { font-family: file-icons; font-size: 15px; content: "\e959"; top: 2px; }
.sqf-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a5"; top: 1px; text-shadow: 0 0 0; }
.sqlite-icon:before { font-family: file-icons; font-size: 15px; content: "\e9dd"; top: 3px; }
.stan-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a4"; top: 2px; }
.stata-icon:before { font-family: file-icons; font-size: 15px; content: "\e9a3"; top: 2px; }
.storyist-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ef"; top: 2px; font-size: 16px; }
.strings-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e0"; top: 2px; }
.stylelint-icon:before { font-family: file-icons; font-size: 15px; content: "\e93d"; top: 2px; }
.stylus-icon:before { font-family: file-icons; font-size: 15px; content: "s"; top: 2px; left: 1px; }
.sublime-icon:before { font-family: file-icons; font-size: 15px; content: "\e986"; top: 2px; }
.svn-icon:before { font-family: file-icons; font-size: 15px; content: "\ea17"; top: 2px; }
.sysverilog-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c3"; top: 2px; }
.tag-icon:before { font-family: file-icons; font-size: 15px; content: "\f015"; top: 2px; font-size: 14px; }
.tcl-icon:before { font-family: file-icons; font-size: 15px; content: "\e956"; top: 2px; font-size: 16px; }
.terminal-icon:before { font-family: file-icons; font-size: 15px; content: "\f0c8"; top: 2px; font-size: 14px; }
.tern-icon:before { font-family: file-icons; font-size: 15px; content: "\1f54a";top: 4px; font-size: 16px; }
.terraform-icon:before { font-family: file-icons; font-size: 15px; content: "\e916"; top: 1px; font-size: 14px; }
.tex-icon:before { font-family: file-icons; font-size: 15px; content: "\e600"; top: 4px; font-size: 16px; -webkit-font-smoothing: subpixel-antialiased; }
.textile-icon:before { font-family: file-icons; font-size: 15px; content: "t"; top: 2px; }
.textmate-icon:before { font-family: file-icons; font-size: 15px; content: "\2122"; top: 2px; font-size: 16px; }
.thor-icon:before { font-family: file-icons; font-size: 15px; content: "\e9d8"; top: 2px; }
.ts-icon:before { font-family: file-icons; font-size: 15px; content: "\2a6"; top: 1px; font-size: 14px; }
.tsx-icon:before { font-family: file-icons; font-size: 15px; content: "\e9e7"; top: 1px; font-size: 14px; }
.turing-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b6"; top: 2px; }
.txl-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c1"; top: 2px; }
.typedoc-icon:before { font-family: file-icons; font-size: 15px; content: "\e9fe"; top: 2px; }
.typings-icon:before { font-family: file-icons; font-size: 15px; content: "\e9df"; top: 2px; }
.uno-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b3"; top: 2px; }
.unreal-icon:before { font-family: file-icons; font-size: 15px; content: "u"; top: 2px; }
.urweb-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ba"; top: 4px; font-size: 18px; left: -1px; text-shadow: 0 0 0; }
.webpack-icon:before { font-family: file-icons; font-size: 15px; content: "\e91e"; top: 3px; }
.wercker-icon:before { font-family: file-icons; font-size: 15px; content: "\ea19"; top: 2px; }
.word-icon:before { font-family: file-icons; font-size: 15px; content: "\e9ed"; top: 2px; }
.v8-icon:before { font-family: file-icons; font-size: 15px; content: "\ea1f"; top: 3px; font-size: 16px; }
.vagrant-icon:before { font-family: file-icons; font-size: 15px; content: "V"; top: 2px; font-size: 14px; }
.varnish-icon:before { font-family: file-icons; font-size: 15px; content: "\e9b4"; top: 1px; font-size: 14px; }
.verilog-icon:before { font-family: file-icons; font-size: 15px; content: "\e949"; top: 2px; }
.vhdl-icon:before { font-family: file-icons; font-size: 15px; content: "\e9aa"; top: 2px; }
.video-icon:before { font-family: file-icons; font-size: 15px; content: "\f057"; top: 1px; font-size: 14px; }
.vue-icon:before { font-family: file-icons; font-size: 15px; content: "\e906"; top: 3px; }
.x10-icon:before { font-family: file-icons; font-size: 15px; content: "\2169"; top: 2px; }
.xmos-icon:before { font-family: file-icons; font-size: 15px; content: "X"; top: 1px; font-size: 14px; }
.xojo-icon:before { font-family: file-icons; font-size: 15px; content: "\e9af"; top: 2px; }
.xpages-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c5"; top: 2px; }
.xtend-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c6"; top: 2px; }
.yang-icon:before { font-family: file-icons; font-size: 15px; content: "\262f"; top: 2px; }
.yarn-icon:before { font-family: file-icons; font-size: 15px; content: "\ea1a"; top: 2px; font-size: 16px; }
.yui-icon:before { font-family: file-icons; font-size: 15px; content: "\ea00"; top: 2px; }
.zbrush-icon:before { font-family: file-icons; font-size: 15px; content: "\e9f2"; top: 2px; font-size: 16px; }
.zephir-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c7"; top: 2px; -webkit-font-smoothing: subpixel-antialiased; }
.zimpl-icon:before { font-family: file-icons; font-size: 15px; content: "\e9c8"; top: 2px; font-size: 16px; left: 1px; }

1426
libs/file-icons.js Normal file

File diff suppressed because it is too large Load Diff

BIN
libs/fonts/devopicons.woff2 Normal file

Binary file not shown.

BIN
libs/fonts/file-icons.woff2 Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/fonts/mfixx.woff2 Normal file

Binary file not shown.

BIN
libs/fonts/octicons.woff2 Normal file

Binary file not shown.

5
libs/jquery.js vendored
View File

@ -325,8 +325,13 @@ jQuery.extend({
} else { } else {
// Otherwise, avoid the DOM node creation, insertion // Otherwise, avoid the DOM node creation, insertion
// and removal by using an indirect global eval // and removal by using an indirect global eval
try{
indirect( code ); indirect( code );
} }
catch(e){
console.log(e)
}
}
} }
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "octotree", "name": "octotree",
"version": "2.2.5", "version": "2.4.3",
"description": "Code tree for GitHub", "description": "Code tree for GitHub",
"main": "inject.js", "main": "inject.js",
"scripts": { "scripts": {
@ -32,6 +32,7 @@
"gulp-babel": "^6.1.0", "gulp-babel": "^6.1.0",
"gulp-clean": "^0.3.1", "gulp-clean": "^0.3.1",
"gulp-concat": "*", "gulp-concat": "*",
"gulp-crx-pack": "^1.0.1",
"gulp-exit": "0.0.2", "gulp-exit": "0.0.2",
"gulp-less": "^1.3.1", "gulp-less": "^1.3.1",
"gulp-load-plugins": "^0.5.3", "gulp-load-plugins": "^0.5.3",

View File

@ -1,7 +1,8 @@
class Adapter { class Adapter {
constructor(deps) { constructor(deps, store) {
deps.forEach(dep => window[dep]()) deps.forEach(dep => window[dep]())
this._defaultBranch = {} this._defaultBranch = {}
this.store = store
} }
/** /**
@ -14,8 +15,9 @@ class Adapter {
* } * }
* @param {Function} transform(item) * @param {Function} transform(item)
* @param {Function} cb(err: error, tree: Array[Array|item]) * @param {Function} cb(err: error, tree: Array[Array|item])
* @api protected
*/ */
_loadCodeTree(opts, transform, cb) { _loadCodeTreeInternal(opts, transform, cb) {
const folders = { '': [] } const folders = { '': [] }
const $dummyDiv = $('<div/>') const $dummyDiv = $('<div/>')
const {path, repo, node} = opts const {path, repo, node} = opts
@ -58,7 +60,59 @@ class Adapter {
item.id = NODE_PREFIX + path item.id = NODE_PREFIX + path
item.text = name item.text = name
item.icon = type // uses `type` as class name for tree node
// uses `type` as class name for tree node
item.icon = type
// @ifdef SUPPORT_FILE_ICONS
if (type === 'blob') {
if (this.store.get(STORE.ICONS)) {
const className = FileIcons.getClassWithColor(name)
item.icon += ' ' + (className || 'file-generic')
}
else {
item.icon += ' file-generic'
}
}
// @endif
// @ifndef SUPPORT_FILE_ICONS
item.icon += ' file-generic'
// @endif
if (item.patch) {
let patch_html = ''
switch (item.patch.action) {
case 'added':
patch_html += '<span class="text-green">added</span>'
break
case 'renamed':
patch_html +=
`<span class="text-green" title="${item.patch.previous}">renamed</span>`
break
case 'removed':
patch_html +=
`<span class="text-red" title="${item.patch.previous}">removed</span>`
break
default:
break
}
if (item.patch.filesChanged) {
const fileString = item.patch.filesChanged === 1 ? 'file' : 'files'
patch_html += `<span>${item.patch.filesChanged} ${fileString}</span>`
}
if (item.patch.additions !== 0) {
patch_html += `<span class="text-green">+${item.patch.additions}</span>`
}
if (item.patch.deletions !== 0) {
patch_html += `<span class="text-red">-${item.patch.deletions}</span>`
}
item.text += `<span class="patch">${patch_html}</span>`
}
if (node) { if (node) {
folders[''].push(item) folders[''].push(item)
@ -74,10 +128,23 @@ class Adapter {
folders[item.path] = item.children = [] folders[item.path] = item.children = []
} }
// if item is part of a PR, jump to that file's diff
if (item.patch && typeof item.patch.diffId === 'number') {
const url = this._getPatchHref(repo, item.patch)
item.a_attr = {
href: url,
'data-download-url': item.url,
'data-download-filename': name,
}
} else {
// encodes but retains the slashes, see #274 // encodes but retains the slashes, see #274
const encodedPath = path.split('/').map(encodeURIComponent).join('/') const encodedPath = path.split('/').map(encodeURIComponent).join('/')
const url = this._getItemHref(repo, type, encodedPath, opts.encodedBranch)
item.a_attr = { item.a_attr = {
href: this._getItemHref(repo, type, path) href: url,
'data-download-url': url,
'data-download-filename': name,
}
} }
} else if (type === 'commit') { } else if (type === 'commit') {
let moduleUrl = submodules[item.path] let moduleUrl = submodules[item.path]
@ -104,6 +171,10 @@ class Adapter {
}) })
} }
/**
* Generic error handler.
* @api protected
*/
_handleError(jqXHR, cb) { _handleError(jqXHR, cb) {
let error, message, needAuth let error, message, needAuth
@ -171,21 +242,11 @@ class Adapter {
}) })
} }
/**
* Inits behaviors after the sidebar is added to the DOM.
* @api public
*/
init($sidebar) {
$sidebar
.resizable({ handles: 'e', minWidth: this.getMinWidth() })
.addClass(this.getCssClass())
}
/** /**
* Returns the CSS class to be added to the Octotree sidebar. * Returns the CSS class to be added to the Octotree sidebar.
* @api protected * @api protected
*/ */
getCssClass() { _getCssClass() {
throw new Error('没有实现的方法') throw new Error('没有实现的方法')
} }
@ -193,10 +254,20 @@ class Adapter {
* Returns the minimum width acceptable for the sidebar. * Returns the minimum width acceptable for the sidebar.
* @api protected * @api protected
*/ */
getMinWidth() { _getMinWidth() {
return 200 return 200
} }
/**
* Inits behaviors after the sidebar is added to the DOM.
* @api public
*/
init($sidebar) {
$sidebar
.resizable({ handles: 'e', minWidth: this._getMinWidth() })
.addClass(this._getCssClass())
}
/** /**
* Returns whether the adapter is capable of loading the entire tree in * Returns whether the adapter is capable of loading the entire tree in
* a single request. This is usually determined by the underlying the API. * a single request. This is usually determined by the underlying the API.
@ -234,7 +305,7 @@ class Adapter {
* Returns repo info at the current path. * Returns repo info at the current path.
* @api public * @api public
*/ */
getRepoFromPath(showInNonCodePage, currentRepo, token, cb) { getRepoFromPath(token, cb) {
throw new Error('没有实现的方法') throw new Error('没有实现的方法')
} }
@ -295,89 +366,14 @@ class Adapter {
* Returns item's href value. * Returns item's href value.
* @api protected * @api protected
*/ */
_getItemHref(repo, type, encodedPath) { _getItemHref(repo, type, encodedPath, encodedBranch) {
return `/${repo.username}/${repo.reponame}/${type}/${repo.branch}/${encodedPath}` return `/${repo.username}/${repo.reponame}/${type}/${encodedBranch}/${encodedPath}`
} }
} /**
* Returns patch's href value.
* @api protected
class PjaxAdapter extends Adapter { */
constructor() { _getPatchHref(repo, patch) {
super(['jquery.pjax.js']) return `/${repo.username}/${repo.reponame}/pull/${repo.pullNumber}/files#diff-${patch.diffId}`
$.pjax.defaults.timeout = 0 // no timeout
$(document)
.on('pjax:send', () => $(document).trigger(EVENT.REQ_START))
.on('pjax:end', () => $(document).trigger(EVENT.REQ_END))
}
// @override
// @param {Object} opts - {pjaxContainer: the specified pjax container}
// @api public
init($sidebar, opts) {
super.init($sidebar)
opts = opts || {}
const pjaxContainer = opts.pjaxContainer
if (!window.MutationObserver) return
// Some host switch pages using pjax. This observer detects if the pjax container
// has been updated with new contents and trigger layout.
const pageChangeObserver = new window.MutationObserver(() => {
// Trigger location change, can't just relayout as Octotree might need to
// hide/show depending on whether the current page is a code page or not.
return $(document).trigger(EVENT.LOC_CHANGE)
})
if (pjaxContainer) {
pageChangeObserver.observe(pjaxContainer, {
childList: true,
})
} else { // Fall back if DOM has been changed
let firstLoad = true, href, hash
function detectLocChange() {
if (location.href !== href || location.hash !== hash) {
href = location.href
hash = location.hash
// If this is the first time this is called, no need to notify change as
// Octotree does its own initialization after loading options.
if (firstLoad) {
firstLoad = false
} else {
setTimeout(() => {
$(document).trigger(EVENT.LOC_CHANGE)
}, 300) // Wait a bit for pjax DOM change
}
}
setTimeout(detectLocChange, 200)
}
detectLocChange()
}
}
// @override
// @param {Object} opts - {$pjax_container: jQuery object}
// @api public
selectFile(path, opts) {
opts = opts || {}
const $pjaxContainer = opts.$pjaxContainer
const fragment = opts.fragment
if ($pjaxContainer.length) {
$.pjax({
// needs full path for pjax to work with Firefox as per cross-domain-content setting
url: location.protocol + '//' + location.host + path,
container: $pjaxContainer,
fragment: fragment
})
} else { // falls back
super.selectFile(path)
}
} }
} }

View File

@ -9,10 +9,6 @@ const BB_PJAX_CONTAINER_SEL = '#source-container'
class Bitbucket extends PjaxAdapter { class Bitbucket extends PjaxAdapter {
constructor() {
super(['jquery.pjax.js'])
}
// @override // @override
init($sidebar) { init($sidebar) {
const pjaxContainer = $(BB_PJAX_CONTAINER_SEL)[0] const pjaxContainer = $(BB_PJAX_CONTAINER_SEL)[0]
@ -20,7 +16,7 @@ class Bitbucket extends PjaxAdapter {
} }
// @override // @override
getCssClass() { _getCssClass() {
return 'octotree_bitbucket_sidebar' return 'octotree_bitbucket_sidebar'
} }
@ -37,7 +33,7 @@ class Bitbucket extends PjaxAdapter {
} }
// @override // @override
getRepoFromPath(showInNonCodePage, currentRepo, token, cb) { getRepoFromPath(currentRepo, token, cb) {
// 404 page, skip // 404 page, skip
if ($(BB_404_SEL).length) { if ($(BB_404_SEL).length) {
@ -63,8 +59,8 @@ class Bitbucket extends PjaxAdapter {
// Skip non-code page unless showInNonCodePage is true // Skip non-code page unless showInNonCodePage is true
// with Bitbucket /username/repo is non-code page // with Bitbucket /username/repo is non-code page
if (!showInNonCodePage && const showInNonCodePage = this.store.get(STORE.NONCODE)
(!type || (type && type !== 'src'))) { if (!showInNonCodePage && (!type || (type && type !== 'src'))) {
return cb() return cb()
} }
@ -102,7 +98,7 @@ class Bitbucket extends PjaxAdapter {
// @override // @override
loadCodeTree(opts, cb) { loadCodeTree(opts, cb) {
opts.path = opts.node.path opts.path = opts.node.path
this._loadCodeTree(opts, (item) => { this._loadCodeTreeInternal(opts, (item) => {
if (!item.type) { if (!item.type) {
item.type = 'blob' item.type = 'blob'
} }
@ -206,7 +202,7 @@ class Bitbucket extends PjaxAdapter {
} }
// @override // @override
_getItemHref(repo, type, encodedPath) { _getItemHref(repo, type, encodedPath, encodedBranch) {
return `/${repo.username}/${repo.reponame}/src/${repo.branch}/${encodedPath}` return `/${repo.username}/${repo.reponame}/src/${encodedBranch}/${encodedPath}`
} }
} }

View File

@ -95,7 +95,7 @@
content: '\f131'; content: '\f131';
color: #707070; color: #707070;
} }
.jstree-icon.blob:before { .jstree-icon.file-generic:before {
content: '\f12e'; content: '\f12e';
color: #707070; color: #707070;
} }
@ -125,7 +125,7 @@
background: #e6e6e6; background: #e6e6e6;
} }
} }
.jstree-icon.tree, .jstree-icon.blob, .jstree-icon.commit { .jstree-icon.tree, .jstree-icon.file-generic, .jstree-icon.commit {
font: normal normal 16px 'Atlassian Icons'; font: normal normal 16px 'Atlassian Icons';
} }
} }

View File

@ -13,13 +13,13 @@ const GH_RESERVED_USER_NAMES = [
const GH_RESERVED_REPO_NAMES = ['followers', 'following', 'repositories'] const GH_RESERVED_REPO_NAMES = ['followers', 'following', 'repositories']
const GH_404_SEL = '#parallax_wrapper' const GH_404_SEL = '#parallax_wrapper'
const GH_PJAX_CONTAINER_SEL = '#js-repo-pjax-container, .context-loader-container, [data-pjax-container]' const GH_PJAX_CONTAINER_SEL = '#js-repo-pjax-container, .context-loader-container, [data-pjax-container]'
const GH_CONTAINERS = '.container, .container-responsive' const GH_CONTAINERS = '.container, .container-lg, .container-responsive'
const GH_RAW_CONTENT = 'body > pre' const GH_RAW_CONTENT = 'body > pre'
class GitHub extends PjaxAdapter { class GitHub extends PjaxAdapter {
constructor() { constructor(store) {
super(['jquery.pjax.js']) super(store)
} }
// @override // @override
@ -47,7 +47,7 @@ class GitHub extends PjaxAdapter {
} }
// @override // @override
getCssClass() { _getCssClass() {
return 'octotree_github_sidebar' return 'octotree_github_sidebar'
} }
@ -58,7 +58,7 @@ class GitHub extends PjaxAdapter {
// @override // @override
getCreateTokenUrl() { getCreateTokenUrl() {
return `${location.protocol}//${location.host}/settings/tokens/new` return `${location.protocol}//${location.host}/settings/tokens/new?scopes=repo&description=Octotree%20browser%20extension`
} }
// @override // @override
@ -73,7 +73,9 @@ class GitHub extends PjaxAdapter {
} }
// @override // @override
getRepoFromPath(showInNonCodePage, currentRepo, token, cb) { getRepoFromPath(currentRepo, token, cb) {
const showInNonCodePage = this.store.get(STORE.NONCODE)
const showOnlyChangedInPR = this.store.get(STORE.PR)
// 404 page, skip // 404 page, skip
if ($(GH_404_SEL).length) { if ($(GH_404_SEL).length) {
@ -85,14 +87,16 @@ class GitHub extends PjaxAdapter {
return cb() return cb()
} }
// (username)/(reponame)[/(type)] // (username)/(reponame)[/(type)][/(typeId)]
const match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?/) const match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?(?:\/([^\/]+))?/)
if (!match) { if (!match) {
return cb() return cb()
} }
const username = match[1] let username = match[1]
const reponame = match[2] let reponame = match[2]
let type = match[3]
let typeId = match[4]
// Not a repository, skip // Not a repository, skip
if (~GH_RESERVED_USER_NAMES.indexOf(username) || if (~GH_RESERVED_USER_NAMES.indexOf(username) ||
@ -100,8 +104,12 @@ class GitHub extends PjaxAdapter {
return cb() return cb()
} }
// Check if this is a PR and whether we should show changes
const isPR = type === 'pull'
const pullNumber = isPR && showOnlyChangedInPR ? typeId : null
// Skip non-code page unless showInNonCodePage is true // Skip non-code page unless showInNonCodePage is true
if (!showInNonCodePage && match[3] && !~['tree', 'blob'].indexOf(match[3])) { if (!showInNonCodePage && type && !~['tree', 'blob'].indexOf(type)) {
return cb() return cb()
} }
@ -117,8 +125,7 @@ class GitHub extends PjaxAdapter {
this._defaultBranch[username + '/' + reponame] this._defaultBranch[username + '/' + reponame]
// Still no luck, get default branch for real // Still no luck, get default branch for real
const repo = {username: username, reponame: reponame, branch: branch} const repo = {username: username, reponame: reponame, branch: branch, pullNumber: pullNumber}
if (repo.branch) { if (repo.branch) {
cb(null, repo) cb(null, repo)
} }
@ -142,16 +149,105 @@ class GitHub extends PjaxAdapter {
opts.encodedBranch = encodeURIComponent(decodeURIComponent(opts.repo.branch)) opts.encodedBranch = encodeURIComponent(decodeURIComponent(opts.repo.branch))
opts.path = (opts.node && (opts.node.sha || opts.encodedBranch)) || opts.path = (opts.node && (opts.node.sha || opts.encodedBranch)) ||
(opts.encodedBranch + '?recursive=1') (opts.encodedBranch + '?recursive=1')
this._loadCodeTree(opts, null, cb) this._loadCodeTreeInternal(opts, null, cb)
} }
// @override // @override
_getTree(path, opts, cb) { _getTree(path, opts, cb) {
if (opts.repo.pullNumber) {
this._getPatch(opts, cb)
}
else {
this._get(`/git/trees/${path}`, opts, (err, res) => { this._get(`/git/trees/${path}`, opts, (err, res) => {
// console.log('****', res.tree);
if (err) cb(err) if (err) cb(err)
else cb(null, res.tree) else cb(null, res.tree)
}) })
} }
}
/**
* Get files that were patched in Pull Request.
* The diff map that is returned contains changed files, as well as the parents of the changed files.
* This allows the tree to be filtered for only folders that contain files with diffs.
* @param {Object} opts: {
* path: the starting path to load the tree,
* repo: the current repository,
* node (optional): the selected node (null to load entire tree),
* token (optional): the personal access token
* }
* @param {Function} cb(err: error, diffMap: Object)
*/
_getPatch(opts, cb) {
const {pullNumber} = opts.repo
this._get(`/pulls/${pullNumber}/files?per_page=300`, opts, (err, res) => {
if (err) cb(err)
else {
const diffMap = {}
res.forEach((file, index) => {
// record file patch info
diffMap[file.filename] = {
type: 'blob',
diffId: index,
action: file.status,
additions: file.additions,
blob_url: file.blob_url,
deletions: file.deletions,
filename: file.filename,
path: file.path,
sha: file.sha
}
// record ancestor folders
const folderPath = file.filename.split('/').slice(0, -1).join('/')
const split = folderPath.split('/')
// aggregate metadata for ancestor folders
split.reduce((path, curr) => {
if (path.length) path = `${path}/${curr}`
else path = `${curr}`
if (diffMap[path] == null) {
diffMap[path] = {
type: 'tree',
filename: path,
filesChanged: 1,
additions: file.additions,
deletions: file.deletions
}
}
else {
diffMap[path].additions += file.additions
diffMap[path].deletions += file.deletions
diffMap[path].filesChanged++
}
return path
}, '')
})
// transform to emulate response from get `tree`
const tree = Object.keys(diffMap).map(fileName => {
const patch = diffMap[fileName]
return {
patch,
path: fileName,
sha: patch.sha,
type: patch.type,
url: patch.blob_url,
}
})
// sort by path, needs to be alphabetical order (so parent folders come before children)
// note: this is still part of the above transform to mimic the behavior of get tree
tree.sort((a, b) => a.path.localeCompare(b.path))
cb(null, tree)
}
})
}
// @override // @override
_getSubmodules(tree, opts, cb) { _getSubmodules(tree, opts, cb) {

View File

@ -50,6 +50,25 @@
content: data-uri('image/svg+xml;charset=UTF-8', './octicons/question.svg'); content: data-uri('image/svg+xml;charset=UTF-8', './octicons/question.svg');
} }
} }
input[type=text], textarea {
padding: 4px 8px;
color: #24292e;
background-color: #fafbfc;
border: 1px solid #d1d5da;
border-radius: 3px;
outline: none;
box-shadow: rgba(27, 31, 35, 0.075) 0px 1px 2px inset;
&:focus {
border-color: #2188ff;
box-shadow: inset 0 1px 2px rgba(27,31,35,0.075), 0 0 0 0.2em rgba(3,102,214,0.3);
}
}
textarea {
padding: 6px 8px;
}
} }
.octotree_treeview { .octotree_treeview {
@ -70,20 +89,23 @@
top: 2px; top: 2px;
content: data-uri('image/svg+xml;charset=UTF-8', './octicons/git-branch.svg'); content: data-uri('image/svg+xml;charset=UTF-8', './octicons/git-branch.svg');
} }
.jstree-icon { .jstree-icon.tree, .jstree-icon.commit, .jstree-icon.blob.file-generic {
margin-top: 3px; margin-top: 3px;
} }
.jstree-icon.tree:before { .jstree-icon.tree:before {
content: data-uri('image/svg+xml;charset=UTF-8', './octicons/file-directory.svg'); content: data-uri('image/svg+xml;charset=UTF-8', './octicons/file-directory.svg');
} }
.jstree-icon.blob:before { .jstree-icon.file-generic:before {
content: data-uri('image/svg+xml;charset=UTF-8', './octicons/file-text.svg'); content: data-uri('image/svg+xml;charset=UTF-8', './octicons/file-text.svg');
} }
.jstree-node.jstree-leaf:hover { .jstree-node.jstree-leaf:hover {
.jstree-icon.blob:before { .jstree-icon.blob {
margin-top: 1px;
&:before {
content: data-uri('image/svg+xml;charset=UTF-8', './octicons/cloud-download.svg'); content: data-uri('image/svg+xml;charset=UTF-8', './octicons/cloud-download.svg');
} }
} }
}
.jstree-icon.commit:before { .jstree-icon.commit:before {
content: data-uri('image/svg+xml;charset=UTF-8', './octicons/file-submodule.svg'); content: data-uri('image/svg+xml;charset=UTF-8', './octicons/file-submodule.svg');
} }
@ -101,6 +123,18 @@
background: #dbeeff; background: #dbeeff;
} }
} }
.patch {
display: none;
}
.patch:last-of-type {
display: inline;
font-size: 80%;
span {
padding-left: 5px;
}
}
} }
} }

View File

@ -1,3 +1,3 @@
<svg style="fill: #777" height="16" width="16" xmlns="http://www.w3.org/2000/svg"> <svg style="fill: #AC4142" height="16" width="16" xmlns="http://www.w3.org/2000/svg">
<path d="M9 13h2l-3 3-3-3h2V8h2v5z m3-8c0-0.44-0.91-3-4.5-3-2.42 0-4.5 1.92-4.5 4C1.02 6 0 7.52 0 9c0 1.53 1 3 3 3 0.44 0 2.66 0 3 0v-1.3H3C1.38 10.7 1.3 9.28 1.3 9c0-0.17 0.05-1.7 1.7-1.7h1.3v-1.3c0-1.39 1.56-2.7 3.2-2.7 2.55 0 3.13 1.55 3.2 1.8v1.2h1.3c0.81 0 2.7 0.22 2.7 2.2 0 2.09-2.25 2.2-2.7 2.2H10v1.3c0.38 0 1.98 0 2 0 2.08 0 4-1.16 4-3.5 0-2.44-1.92-3.5-4-3.5z" /> <path d="M9 13h2l-3 3-3-3h2V8h2v5z m3-8c0-0.44-0.91-3-4.5-3-2.42 0-4.5 1.92-4.5 4C1.02 6 0 7.52 0 9c0 1.53 1 3 3 3 0.44 0 2.66 0 3 0v-1.3H3C1.38 10.7 1.3 9.28 1.3 9c0-0.17 0.05-1.7 1.7-1.7h1.3v-1.3c0-1.39 1.56-2.7 3.2-2.7 2.55 0 3.13 1.55 3.2 1.8v1.2h1.3c0.81 0 2.7 0.22 2.7 2.2 0 2.09-2.25 2.2-2.7 2.2H10v1.3c0.38 0 1.98 0 2 0 2.08 0 4-1.16 4-3.5 0-2.44-1.92-3.5-4-3.5z" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 467 B

After

Width:  |  Height:  |  Size: 470 B

View File

@ -7,8 +7,8 @@ const OSC_RAW_CONTENT = 'body > pre'
class Oschina extends PjaxAdapter { class Oschina extends PjaxAdapter {
constructor() { constructor(store) {
super(['jquery.pjax.js']) super(store)
} }
// @override // @override
@ -36,7 +36,7 @@ class Oschina extends PjaxAdapter {
} }
// @override // @override
getCssClass() { _getCssClass() {
return 'octotree_oschina_sidebar' return 'octotree_oschina_sidebar'
} }
@ -66,7 +66,8 @@ class Oschina extends PjaxAdapter {
} }
// @override // @override
getRepoFromPath(showInNonCodePage, currentRepo, token, cb) { getRepoFromPath(currentRepo, token, cb) {
const showInNonCodePage = this.store.get(STORE.NONCODE)
// 404 page, skip // 404 page, skip
if ($(OSC_404_SEL).length) { if ($(OSC_404_SEL).length) {
@ -125,6 +126,7 @@ class Oschina extends PjaxAdapter {
// @override // @override
selectFile(path) { selectFile(path) {
console.log('select file: ' + path)
const $pjaxContainer = $(OSC_PJAX_CONTAINER_SEL) const $pjaxContainer = $(OSC_PJAX_CONTAINER_SEL)
super.selectFile(path, { '$pjaxContainer': $pjaxContainer, fragment: OSC_PJAX_CONTAINER_SEL }) super.selectFile(path, { '$pjaxContainer': $pjaxContainer, fragment: OSC_PJAX_CONTAINER_SEL })
} }
@ -134,7 +136,7 @@ class Oschina extends PjaxAdapter {
opts.encodedBranch = encodeURIComponent(decodeURIComponent(opts.repo.branch)) opts.encodedBranch = encodeURIComponent(decodeURIComponent(opts.repo.branch))
opts.path = (opts.node && (opts.node.sha || opts.encodedBranch)) || opts.path = (opts.node && (opts.node.sha || opts.encodedBranch)) ||
(opts.encodedBranch + '?recursive=1') (opts.encodedBranch + '?recursive=1')
this._loadCodeTree(opts, null, cb) this._loadCodeTreeInternal(opts, null, cb)
} }
// @override // @override

87
src/adapters/pjax.js Normal file
View File

@ -0,0 +1,87 @@
class PjaxAdapter extends Adapter {
constructor(store) {
super(['jquery.pjax.js'], store)
$.pjax.defaults.timeout = 0 // no timeout
$(document)
.on('pjax:send', () => $(document).trigger(EVENT.REQ_START))
.on('pjax:end', () => $(document).trigger(EVENT.REQ_END))
}
// @override
// @param {Object} opts - {pjaxContainer: the specified pjax container}
// @api public
init($sidebar, opts) {
super.init($sidebar)
opts = opts || {}
const pjaxContainer = opts.pjaxContainer
if (!window.MutationObserver) return
// Some host switch pages using pjax. This observer detects if the pjax container
// has been updated with new contents and trigger layout.
const pageChangeObserver = new window.MutationObserver(() => {
// Trigger location change, can't just relayout as Octotree might need to
// hide/show depending on whether the current page is a code page or not.
return $(document).trigger(EVENT.LOC_CHANGE)
})
if (pjaxContainer) {
pageChangeObserver.observe(pjaxContainer, {
childList: true,
})
}
else { // Fall back if DOM has been changed
let firstLoad = true, href, hash
function detectLocChange() {
if (location.href !== href || location.hash !== hash) {
href = location.href
hash = location.hash
// If this is the first time this is called, no need to notify change as
// Octotree does its own initialization after loading options.
if (firstLoad) {
firstLoad = false
}
else {
setTimeout(() => {
$(document).trigger(EVENT.LOC_CHANGE)
}, 300) // Wait a bit for pjax DOM change
}
}
setTimeout(detectLocChange, 200)
}
detectLocChange()
}
}
// @override
// @param {Object} opts - {$pjax_container: jQuery object}
// @api public
selectFile(path, opts) {
opts = opts || {}
const $pjaxContainer = opts.$pjaxContainer
const fragment = opts.fragment
// if we're on the same page and just navigating to a different anchor
// don't bother fetching the page with pjax
const pathWithoutAnchor = path.replace(/#.*$/, '')
const isSamePage = location.pathname === pathWithoutAnchor
const loadWithPjax = $pjaxContainer.length && !isSamePage
if (loadWithPjax) {
$.pjax({
// needs full path for pjax to work with Firefox as per cross-domain-content setting
url: location.protocol + '//' + location.host + path,
container: $pjaxContainer,
fragment: fragment
})
}
else {
super.selectFile(path)
}
}
}

View File

@ -11,10 +11,12 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
const cssFiles = [ const cssFiles = [
'jstree.css', 'jstree.css',
'file-icons.css',
'octotree.css' 'octotree.css'
] ]
const jsFiles = [ const jsFiles = [
'file-icons.js',
'jquery.js', 'jquery.js',
'jquery-ui.js', 'jquery-ui.js',
'jstree.js', 'jstree.js',
@ -50,7 +52,8 @@ chrome.runtime.onMessage.addListener((req, sender, sendRes) => {
if (urls.length === 0) { if (urls.length === 0) {
sendRes(true) sendRes(true)
removeUnnecessaryPermissions() removeUnnecessaryPermissions()
} else { }
else {
chrome.permissions.request({ origins: urls }, (granted) => { chrome.permissions.request({ origins: urls }, (granted) => {
sendRes(granted) sendRes(granted)
removeUnnecessaryPermissions() removeUnnecessaryPermissions()
@ -60,7 +63,8 @@ chrome.runtime.onMessage.addListener((req, sender, sendRes) => {
function removeUnnecessaryPermissions() { function removeUnnecessaryPermissions() {
const whitelist = urls.concat([ const whitelist = urls.concat([
'https://github.com/*' 'https://github.com/*',
'https://bitbucket.org/*'
]) ])
chrome.permissions.getAll((permissions) => { chrome.permissions.getAll((permissions) => {
const toBeRemovedUrls = permissions.origins.filter((url) => { const toBeRemovedUrls = permissions.origins.filter((url) => {

View File

@ -3,27 +3,26 @@
"version": "$VERSION", "version": "$VERSION",
"manifest_version": 2, "manifest_version": 2,
"author": "inu1255", "author": "inu1255",
"description": "基于octotree的[码云](http://gitee.com)文件树插件", "description": "基于 Octotree 的[码云](http://gitee.com)文件树插件",
"homepage_url": "http://git.oschina.net/inu1255/GitCodeTree", "homepage_url": "https://gitee.com/inu1255/GitCodeTree",
"icons": { "icons": {
"128": "icons/icon128.png" "128": "icons/icon128.png"
}, },
"permissions": [ "permissions": [
"https://bitbucket.org/*",
"https://github.com/*", "https://github.com/*",
"http://git.oschina.net/*", "http://git.oschina.net/*",
"https://git.oschina.net/*", "https://git.oschina.net/*",
"http://gitee.com/*", "http://gitee.com/*",
"https://gitee.com/*", "https://gitee.com/*",
"https://bitbucket.org/*",
"storage" "storage"
], ],
"optional_permissions": [ "optional_permissions": [
"<all_urls>" "<all_urls>"
], ],
"web_accessible_resources": ["*.woff2"],
"background": { "background": {
"scripts": [ "scripts": ["background.js"],
"background.js"
],
"persistent": false "persistent": false
} }
} }

View File

@ -1,17 +0,0 @@
const data = require('sdk/self').data
const pageMod = require('sdk/page-mod')
pageMod.PageMod({
include: ['https://bitbucket.org/*', 'https://github.com/*', 'https://git.oschina.com/*', 'https://gitee.com/*'],
contentScriptFile: [data.url('jquery.js'),
data.url('jquery-ui.js'),
data.url('jstree.js'),
data.url('keymaster.js'),
data.url('ondemand.js'),
data.url('octotree.js')
],
contentStyleFile: [data.url('jstree.css'),
data.url('octotree.css')
],
contentScriptWhen: 'start'
})

View File

@ -0,0 +1,40 @@
{
"name": "Octotree",
"version": "$VERSION",
"manifest_version": 2,
"author": "inu1255",
"description": "基于 Octotree 的[码云](http://gitee.com)文件树插件",
"homepage_url": "https://gitee.com/inu1255/GitCodeTree",
"icons": {
"48": "icons/icon48.png",
"64": "icons/icon64.png"
},
"permissions": [
"https://*.github.com/*",
"https://*.bitbucket.org/*",
"storage"
],
"web_accessible_resources": ["*.woff2"],
"content_scripts": [
{
"matches": [
"https://github.com/*",
"https://bitbucket.org/*"
],
"js": [
"file-icons.js",
"jquery.js",
"jquery-ui.js",
"jstree.js",
"keymaster.js",
"ondemand.js",
"octotree.js"
],
"css": [
"file-icons.css",
"jstree.css",
"octotree.css"
]
}
]
}

View File

@ -1,25 +0,0 @@
{
"name": "GitCodeTree",
"title": "GitCodeTree",
"id": "929909260@qq.com",
"description": "基于octotree的[码云](http://gitee.com)文件树插件",
"author": "inu1255",
"homepage": "http://git.oschina.net/inu1255/GitCodeTree",
"main": "lib/firefox",
"icon": "resource://jid1-Om7eJGwA1U8Akg-at-jetpack/data/icons/icon48.png",
"icon64": "resource://jid1-Om7eJGwA1U8Akg-at-jetpack/data/icons/icon64.png",
"license": "MIT",
"version": "$VERSION",
"permissions": {
"cross-domain-content": [
"https://api.bitbucket.org",
"https://api.github.com",
"https://bitbucket.org",
"https://git.oschina.net",
"https://gitee.com",
"https://github.com"
],
"private-browsing": true,
"multiprocess": true
}
}

View File

@ -48,7 +48,7 @@
</array> </array>
</dict> </dict>
<key>Description</key> <key>Description</key>
<string>基于octotree的[码云](http://git.oschina.net)文件树插件</string> <string>基于 Octotree 的[码云](http://git.oschina.net)文件树插件</string>
<key>ExtensionInfoDictionaryVersion</key> <key>ExtensionInfoDictionaryVersion</key>
<string>1.0</string> <string>1.0</string>
<key>Permissions</key> <key>Permissions</key>

View File

@ -6,7 +6,9 @@ const STORE = {
TOKEN : 'octotree.access_token', TOKEN : 'octotree.access_token',
REMEMBER : 'octotree.remember', REMEMBER : 'octotree.remember',
NONCODE : 'octotree.noncode_shown', NONCODE : 'octotree.noncode_shown',
PR : 'octotree.pr_shown',
HOTKEYS : 'octotree.hotkeys', HOTKEYS : 'octotree.hotkeys',
ICONS : 'octotree.icons',
LOADALL : 'octotree.loadall', LOADALL : 'octotree.loadall',
POPUP : 'octotree.popup_shown', POPUP : 'octotree.popup_shown',
WIDTH : 'octotree.sidebar_width', WIDTH : 'octotree.sidebar_width',
@ -19,8 +21,10 @@ const DEFAULTS = {
TOKEN : '', TOKEN : '',
REMEMBER : true, REMEMBER : true,
NONCODE : true, NONCODE : true,
PR : true,
LOADALL : true, LOADALL : true,
HOTKEYS : '⌘+⇧+s, ⌃+⇧+s', HOTKEYS : '⌘+⇧+s, ⌃+⇧+s',
ICONS : true,
POPUP : false, POPUP : false,
WIDTH : 232, WIDTH : 232,
SHOWN : false, SHOWN : false,

View File

@ -18,10 +18,13 @@ $(document).ready(() => {
.concat('https://github.com') .concat('https://github.com')
const bitbucketUrls = ['https://bitbucket.org'] const bitbucketUrls = ['https://bitbucket.org']
const oschinaUrls = ['http://git.oschina.net', 'https://git.oschina.net', 'http://gitee.com', 'https://gitee.com'] const oschinaUrls = [
'http://git.oschina.net', 'https://git.oschina.net',
'http://gitee.com', 'https://gitee.com'
]
const currentUrl = `${location.protocol}//${location.host}` const currentUrl = `${location.protocol}//${location.host}`
if (oschinaUrls.indexOf(currentUrl) >= 0) { if (~oschinaUrls.indexOf(currentUrl)) {
return new Oschina(store) return new Oschina(store)
} else if (~githubUrls.indexOf(currentUrl)) { } else if (~githubUrls.indexOf(currentUrl)) {
return new GitHub(store) return new GitHub(store)
@ -78,20 +81,9 @@ $(document).ready(() => {
$sidebar $sidebar
.width(parseInt(store.get(STORE.WIDTH))) .width(parseInt(store.get(STORE.WIDTH)))
.resize(layoutChanged) .resize(() => layoutChanged(true))
.appendTo($('body')) .appendTo($('body'))
var prev = location.href
function aa() {
setTimeout(function() {
if (prev != location.href) {
tryLoadRepo()
prev = location.href
}
aa()
}, 500)
}
aa()
adapter.init($sidebar) adapter.init($sidebar)
return tryLoadRepo() return tryLoadRepo()
@ -100,9 +92,11 @@ $(document).ready(() => {
Object.keys(changes).forEach((storeKey) => { Object.keys(changes).forEach((storeKey) => {
const value = changes[storeKey] const value = changes[storeKey]
switch (storeKey) { switch (storeKey) {
case STORE.TOKEN: case STORE.TOKEN:
case STORE.LOADALL: case STORE.LOADALL:
case STORE.ICONS:
reload = true reload = true
break break
case STORE.HOTKEYS: case STORE.HOTKEYS:
@ -120,14 +114,14 @@ $(document).ready(() => {
function tryLoadRepo(reload) { function tryLoadRepo(reload) {
hasError = false hasError = false
const remember = store.get(STORE.REMEMBER) const remember = store.get(STORE.REMEMBER)
const showInNonCodePage = store.get(STORE.NONCODE)
const shown = store.get(STORE.SHOWN) const shown = store.get(STORE.SHOWN)
const token = store.get(STORE.TOKEN) const token = store.get(STORE.TOKEN)
adapter.getRepoFromPath(showInNonCodePage, currRepo, token, (err, repo) => { adapter.getRepoFromPath(currRepo, token, (err, repo) => {
if (err) { if (err) {
showError(err) showError(err)
} else if (repo) { }
else if (repo) {
$toggler.show() $toggler.show()
if (remember && shown) { if (remember && shown) {
@ -135,18 +129,19 @@ $(document).ready(() => {
} }
if (isSidebarVisible()) { if (isSidebarVisible()) {
const replacer = ['username', 'reponame', 'branch'] const replacer = ['username', 'reponame', 'branch', 'pullNumber']
const repoChanged = JSON.stringify(repo, replacer) !== JSON.stringify(currRepo, replacer) const repoChanged = JSON.stringify(repo, replacer) !== JSON.stringify(currRepo, replacer)
if (repoChanged || reload === true) { if (repoChanged || reload === true) {
$document.trigger(EVENT.REQ_START) $document.trigger(EVENT.REQ_START)
currRepo = repo currRepo = repo
treeView.show(repo, token) treeView.show(repo, token)
} else { }
else {
treeView.syncSelection() treeView.syncSelection()
} }
} }
} else { }
else {
$toggler.hide() $toggler.hide()
toggleSidebar(false) toggleSidebar(false)
} }
@ -178,17 +173,20 @@ $(document).ready(() => {
if (visibility !== undefined) { if (visibility !== undefined) {
if (isSidebarVisible() === visibility) return if (isSidebarVisible() === visibility) return
toggleSidebar() toggleSidebar()
} else { }
else {
$html.toggleClass(SHOW_CLASS) $html.toggleClass(SHOW_CLASS)
$document.trigger(EVENT.TOGGLE, isSidebarVisible()) $document.trigger(EVENT.TOGGLE, isSidebarVisible())
} }
} }
function layoutChanged() { function layoutChanged(save = false) {
const width = $sidebar.outerWidth() const width = $sidebar.outerWidth()
adapter.updateLayout(isTogglerVisible(), isSidebarVisible(), width) adapter.updateLayout(isTogglerVisible(), isSidebarVisible(), width)
if (save === true) {
store.set(STORE.WIDTH, width) store.set(STORE.WIDTH, width)
} }
}
function isSidebarVisible() { function isSidebarVisible() {
return $html.hasClass(SHOW_CLASS) return $html.hasClass(SHOW_CLASS)

View File

@ -116,6 +116,7 @@
} }
.jstree-default .jstree-icon, .jstree-default .jstree-icon:empty, .jstree-default .jstree-anchor { .jstree-default .jstree-icon, .jstree-default .jstree-icon:empty, .jstree-default .jstree-anchor {
line-height: 24px !important; line-height: 24px !important;
font-style: normal;
} }
} }
@ -169,6 +170,13 @@
height: 60px; height: 60px;
} }
} }
.octotree_opts_disclaimer {
color: gray;
display: block;
font-size: 12px;
margin-left: 17px;
}
} }
} }

View File

@ -69,6 +69,14 @@
<label><input type="checkbox" data-store="LOADALL"> 自动加载</label> <label><input type="checkbox" data-store="LOADALL"> 自动加载</label>
</div> </div>
<div class="octotree_github_only">
<label>
<input type="checkbox" data-store="PR">
Show only pull request changes
<span class="octotree_opts_disclaimer">Note: maximum of 300 files</span>
</label>
</div>
<div> <div>
<button type="submit" class="btn">保存</button> <button type="submit" class="btn">保存</button>
</div> </div>

View File

@ -1,6 +1,13 @@
class Storage { class Storage {
set(key, val, cb) { set(key, val, cb) {
try {
localStorage.setItem(key, JSON.stringify(val)) localStorage.setItem(key, JSON.stringify(val))
}
catch (e) {
const msg = 'Octotree cannot save its settings. ' +
'If the local storage for this domain is full, please clean it up and try again.'
console.error(msg, e)
}
if (cb) cb() if (cb) cb()
} }

View File

@ -47,7 +47,7 @@ class OptionsView {
* Certainly not a good place to put this logic but Chrome requires * Certainly not a good place to put this logic but Chrome requires
* permissions to be requested only in response of user input. So... * permissions to be requested only in response of user input. So...
*/ */
// @ifdef CHROME // @ifdef SUPPORT_GHE
const $ta = this.$view.find('[data-store$=EURLS]').filter(':visible') const $ta = this.$view.find('[data-store$=EURLS]').filter(':visible')
if ($ta.length > 0) { if ($ta.length > 0) {
const storeKey = $ta.data('store') const storeKey = $ta.data('store')

View File

@ -21,8 +21,9 @@ class TreeView {
const $jstree = this.$jstree const $jstree = this.$jstree
$jstree.settings.core.data = (node, cb) => { $jstree.settings.core.data = (node, cb) => {
const loadAll = this.adapter.canLoadEntireTree() && const prMode = this.store.get(STORE.PR) && repo.pullNumber
this.store.get(STORE.LOADALL) const loadAll = this.adapter.canLoadEntireTree() && (prMode || this.store.get(STORE.LOADALL))
node = !loadAll && (node.id === '#' ? {path: ''} : node.original) node = !loadAll && (node.id === '#' ? {path: ''} : node.original)
this.adapter.loadCodeTree({repo, token, node}, (err, treeData) => { this.adapter.loadCodeTree({repo, token, node}, (err, treeData) => {
@ -138,7 +139,9 @@ class TreeView {
} }
else if ($icon.hasClass('blob')) { else if ($icon.hasClass('blob')) {
if (download) { if (download) {
adapter.downloadFile(href, $target.text()) const downloadUrl = $target.attr('data-download-url')
const downloadFileName = $target.attr('data-download-filename')
adapter.downloadFile(downloadUrl, downloadFileName)
} }
else { else {
refocusAfterCompletion() refocusAfterCompletion()