├── .gitignore
├── LICENSE
├── README.md
├── bin
└── sfile
├── docs
└── quicksearch.png
├── lib
└── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .idea/
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 staticfile
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 介绍
2 |
3 | [staticfile.org](http://staticfile.org)命令行工具
4 |
5 | # 安装
6 |
7 | ```
8 | npm install -g sfile
9 | ```
10 |
11 | # 使用
12 |
13 | ## 快捷搜索
14 |
15 | 快速搜索关键字
16 |
17 | ```
18 | sfile [library]
19 | ```
20 |
21 | 
22 |
23 | ## 搜索
24 |
25 | 搜索关键字
26 |
27 | ```
28 | sfile search [library]
29 |
30 | Options:
31 | -s, --ssl Output HTTPS link
32 | -h, --html Output HTML
33 | -j, --jade Output Jade Markup
34 | -n, --no-link Do not show the link for latest version
35 | ```
36 |
37 | ## 获取链接
38 |
39 | 获取一个库的所有文件链接
40 |
41 | ```
42 | sfile get [library]
43 |
44 | Options:
45 | -s, --ssl Output HTTPS link
46 | -h, --html Output HTML
47 | -j, --jade Output Jade Markup
48 | -v, --version Use given version, leave empty if you want to see all supported version
49 | -c, --copy Copy to your system clipboard
50 | ```
51 |
52 | ## 查看版本
53 |
54 | ```
55 | sfile --version
56 | ```
57 |
--------------------------------------------------------------------------------
/bin/sfile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var sfile = require('../lib')
3 | , clip = require('cliparoo')
4 | , opt = require('optimist')
5 | , argv = opt
6 | .usage("[Usage]\n\nsfile [command|library]\n\nCommands:\n\n s, search [library]\tTo search the library...\n g, get [library]\tTo get the library assets links...")
7 | .argv;
8 |
9 | switch (argv._[0]) {
10 | case 'i':
11 | case 'info':
12 | var prettyjson = require('prettyjson')
13 | var keyword = argv._[1];
14 | if (!keyword || argv.help) {
15 | opt.showHelp();
16 | return;
17 | }
18 | keyword = keyword.trim();
19 |
20 | sfile.info(keyword, function (err, data) {
21 | if (err) {
22 | return sfile.error(err);
23 | }
24 |
25 | if (data.assets) {
26 | data.assets = [data.assets[0]]
27 | }
28 |
29 | console.log(prettyjson.render(data));
30 | })
31 | break;
32 | case 'search':
33 | case 's':
34 | argv = opt
35 | .usage("sfile " + argv._[0] + " [library]")
36 | .alias('s', 'ssl')
37 | .alias('h', 'html')
38 | .alias('j', 'jade')
39 | .alias('n', 'no-link')
40 | .describe('s', 'Output HTTPS link')
41 | .describe('h', 'Output HTML')
42 | .describe('j', 'Output Jade Markup')
43 | .describe('n', 'Do not show the link for latest version')
44 | .argv;
45 |
46 | var keyword = argv._[1];
47 | if (!keyword || argv.help) {
48 | opt.showHelp();
49 | return;
50 | }
51 | keyword = keyword.trim();
52 |
53 | sfile.search(keyword, function (err, data) {
54 | if (err) return sfile.error(err);
55 |
56 | if (!data.total) {
57 | return printLn("没有结果");
58 | }
59 |
60 | printLn(("搜索 " + keyword.bold + " 共有 " + (data.total + "").bold + " 个库,当前列出 " + (data.libs.length + "").bold + " 个:"));
61 | printLn("");
62 |
63 | data.libs.forEach(function (lib, index) {
64 | printLn(((index > 9 ? index : " " + index) + ")").grey + " " + lib.name.replace(keyword, keyword.bold) + " [" + lib.version.green + "]");
65 |
66 | if (!argv.n) {
67 | var url = sfile.url("/" + lib.name + "/" + lib.version + "/" + lib.filename, argv.ssl);
68 |
69 | if (argv.html) {
70 | url = sfile.html(url);
71 | } else if (argv.jade) {
72 | url = sfile.jade(url);
73 | }
74 |
75 | printLn((" " + url).grey);
76 | }
77 |
78 | printLn("");
79 | });
80 | });
81 | break;
82 | case "get":
83 | case "g":
84 | argv = opt
85 | .usage("sfile " + argv._[0] + " [library]")
86 | .alias('h', 'html')
87 | .alias('j', 'jade')
88 | .alias('s', 'ssl')
89 | .alias('c', 'copy')
90 | .alias('v', 'version')
91 | .describe('v', 'Use given version, leave empty if you want to see all supported version ')
92 | .describe('h', 'Output HTML')
93 | .describe('j', 'Output Jade Markup')
94 | .describe('s', 'Output HTTPS link')
95 | .describe('c', 'Copy to your system clipboard')
96 | .argv;
97 |
98 | var keyword = argv._[1];
99 | if (!keyword || argv.help) {
100 | opt.showHelp();
101 | return;
102 | }
103 | keyword = keyword.trim();
104 | sfile.get(keyword, function (err, lib, suggest) {
105 | if (err) return sfile.error(err);
106 |
107 | if (!lib) {
108 | printLn("未找到库: " + keyword);
109 | // 搜索建议
110 | if (suggest.length > 0) {
111 | printLn("");
112 | for (var i in suggest) {
113 | suggest[i] = suggest[i].underline;
114 | }
115 | printLn("你是不是要找: ".cyan + suggest.slice(0, 5).join(" "));
116 | }
117 | return;
118 | }
119 |
120 | var version = (argv.version && argv.version !== true) ? argv.version : "" + lib.version;
121 | var matched = false;
122 |
123 | // 匹配package.json给出的版本
124 | lib.assets.forEach(function (asset) {
125 | if (asset.version == version) {
126 | if (matched) return;
127 | matched = asset;
128 | }
129 | });
130 |
131 | // 未匹配容错
132 | if (!matched && lib.assets[0] && !argv.version) {
133 | matched = lib.assets[0];
134 | }
135 |
136 | if (!matched) {
137 | printLn("未找到 " + keyword + " [" + (argv.version + "").red + "]");
138 | } else {
139 | printLn("找到 " + lib.name.bold + " [" + version.green + "]:");
140 | printLn("");
141 |
142 | var urls = [];
143 | matched.files.forEach(function (file) {
144 | var path = "/" + lib.name + "/" + version + "/" + file;
145 | var url = sfile.url(path, argv.ssl);
146 | if (argv.html) {
147 | url = sfile.html(url);
148 | } else if (argv.jade) {
149 | url = sfile.jade(url);
150 | }
151 |
152 | url && printLn(url) && urls.push(url);
153 | });
154 |
155 | // 复制到剪贴板
156 | if (argv.copy) {
157 | clip(urls.join(argv.html || argv.jade ? "\n" : "\\\\n"), function (err) {
158 | if (err) return sfile.error(err);
159 |
160 | printLn("✔ 已复制到剪贴板".green);
161 | });
162 | }
163 | }
164 | printLn("");
165 | if (argv.version)
166 | printLn("支持的版本号: ".cyan + lib.assets.map(function (asset) {
167 | return asset.version.underline
168 | }).join(" "));
169 | });
170 | break
171 | default:
172 | if (argv.version || argv.v) {
173 | var json = require("../package.json");
174 | printLn(json.version);
175 | } else if (argv._[0]) {
176 | var List = require('term-list')
177 | , list = new List({ marker: '\033[36m› \033[0m', markerLength: 2 })
178 | , styles = ['', 'html', 'jade']
179 | , current_style_index = 0
180 |
181 | keyword = argv._[0].trim();
182 |
183 | sfile.search(keyword, function (err, data) {
184 | if (err) return sfile.error(err);
185 |
186 | if (!data.total) {
187 | return printLn("没有结果");
188 | }
189 |
190 | printLn(("搜索 " + keyword.bold + " 共有 " + (data.total + "").bold + " 个库,当前列出 " + (data.libs.length + "").bold + " 个:"));
191 |
192 | data.libs.forEach(function (lib, index) {
193 | var url = sfile.url("/" + lib.name + "/" + lib.version + "/" + lib.filename);
194 | lib.index = index;
195 | lib.base = lib.name.replace(keyword, keyword.bold) + " [" + lib.version.green + "] ";
196 | lib.url = url;
197 | lib.to_copy = url;
198 | lib.subLabel = lib.filename;
199 | lib.current = 'url';
200 | list.add(lib, lib.base + lib.subLabel.grey);
201 | });
202 |
203 | var changeStyle = function (reverse) {
204 | if (reverse) {
205 | current_style_index = current_style_index - 1 < 0 ? 2 : current_style_index - 1;
206 | } else {
207 | current_style_index = current_style_index + 1 > 2 ? 0 : current_style_index + 1;
208 | }
209 | var current_style = styles[current_style_index];
210 |
211 | list.items.forEach(function (it, i) {
212 | var current = list.at(i);
213 | current.label = it.id.base + it.id.subLabel.grey + (current_style && (' [' + current_style + ']').red);
214 | current.id.to_copy = current_style ? sfile[current_style](it.id.url) : it.id.url;
215 | });
216 | list.draw();
217 | }
218 |
219 | list.start();
220 |
221 | list.on("keypress", function (key, item) {
222 | switch (key.name) {
223 | case "return":
224 | clip(item.to_copy, function (err) {
225 | if (err) return sfile.error(err);
226 |
227 | printLn("✔ 已复制到剪贴板".green);
228 | });
229 | list.stop();
230 | break;
231 | case "left":
232 | changeStyle(true);
233 | break;
234 | case "right":
235 | changeStyle(false);
236 | break;
237 | }
238 | });
239 |
240 | list.on('empty', function () {
241 | list.stop();
242 | });
243 | });
244 | } else {
245 | opt.showHelp();
246 | }
247 | }
248 |
249 | function printLn() {
250 | var args = Array.prototype.slice.call(arguments, 0);
251 | args[0] = " " + args[0];
252 | console.log.apply(this, args);
253 | return true;
254 | }
255 |
--------------------------------------------------------------------------------
/docs/quicksearch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/staticfile/cli/4c8ee8728a0b817d187130a28df93e1a19b1405a/docs/quicksearch.png
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | var request = require('request')
2 | , colors = require('colors')
3 | , url = "http://api.staticfile.org/v1/search?count=10&q="
4 | , show_url = "http://api.staticfile.org/v1/packages/"
5 |
6 | exports.search = function (keyword, cb) {
7 | request.get({url: url + encodeURIComponent(keyword), json: true}, function (err, response, data) {
8 | return cb(err, data);
9 | });
10 | };
11 |
12 | exports.get = function (keyword, cb) {
13 | request.get({url: url + encodeURIComponent(keyword), json: true}, function (err, response, data) {
14 | if (err) return cb(err);
15 |
16 | if (!data.libs) return cb(null, false);
17 |
18 | var matched_lib = false;
19 | var suggest = [];
20 |
21 | data.libs.forEach(function (lib) {
22 | if (lib.name.toLowerCase() == keyword.toLowerCase()) matched_lib = lib;
23 | suggest.push(lib.name);
24 | });
25 |
26 | return cb(null, matched_lib, suggest);
27 | });
28 | };
29 |
30 | exports.info = function (keyword, cb) {
31 | request.get({url: show_url + encodeURIComponent(keyword), json: true}, function (err, response, data) {
32 | if (err) return cb(err);
33 |
34 | if (data.hasOwnProperty('success') && !data.success) return cb(new Error("Package '" + keyword + "' not exist"));
35 |
36 | return cb(null, data);
37 | });
38 | }
39 |
40 | exports.error = function (e) {
41 | console.log("错误".redBG + " " + (e instanceof Object ? e.message : e));
42 | };
43 |
44 | exports.loading = function () {
45 | console.log("加载中...".grey);
46 | };
47 |
48 | exports.html = function (file) {
49 | var ext = exports.ext(file);
50 | switch (ext) {
51 | case "js":
52 | return '';
53 | break;
54 | case 'css':
55 | return '';
56 | break;
57 | default:
58 | return false;
59 | }
60 | };
61 |
62 | exports.jade = function (file) {
63 | var ext = exports.ext(file);
64 | switch (ext) {
65 | case "js":
66 | return 'script(type="text/javascript" src="' + file + '")'
67 | break;
68 | case 'css':
69 | return 'link(type="text/css" rel="stylesheet" href="' + file + '")';
70 | break;
71 | default:
72 | return false;
73 | }
74 | };
75 |
76 | exports.ext = function (filename) {
77 | var i = filename.lastIndexOf('.');
78 | return (i < 0) ? '' : filename.substr(i + 1);
79 | };
80 |
81 | exports.url = function (path, ssl) {
82 | ssl = ssl || false;
83 |
84 | return (ssl ? '//dn-staticfile.qbox.me' : 'http://cdn.staticfile.org') + path;
85 | };
86 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sfile",
3 | "version": "0.1.2",
4 | "description": "The static library search and cli for staticfile.org.",
5 | "author": "hfcorriez ",
6 | "licenses": [
7 | {
8 | "type": "MIT",
9 | "url": "https://github.com/staticfile/cli/blob/master/LICENSE"
10 | }
11 | ],
12 | "homepage": "http://staticfile.org",
13 | "engines": {
14 | "node": "*"
15 | },
16 | "dependencies": {
17 | "optimist": "0.6.0",
18 | "colors": "0.6.2",
19 | "request": "2.27.0",
20 | "cliparoo": "1.0.0",
21 | "term-list": "0.2.0",
22 | "prettyjson": "~0.12.0"
23 | },
24 | "bin": {
25 | "sfile": "bin/sfile"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------