├── news └── harvest ├── .gitignore ├── src ├── list.md ├── new.md ├── harvest-bootstrap.js ├── build.js └── harvest.js ├── package.json ├── _README.md ├── config.js └── README.md /news/harvest: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | src/_list.md 3 | news/*.md 4 | *.log 5 | -------------------------------------------------------------------------------- /src/list.md: -------------------------------------------------------------------------------- 1 | <% for (var i = 0; i < blogs.length; i ++) { 2 | var blog = blogs[i] 3 | %> 4 | - [<%= blog.full_name %>(<%= blog.open_issues_count %>)](<%= blog.html_url %>) ✯<%= blog.stargazers_count %> 5 | <% } %> -------------------------------------------------------------------------------- /src/new.md: -------------------------------------------------------------------------------- 1 | <% for (var i = 0; i < items.length; i ++) { 2 | var item = items[i] 3 | %> 4 | - [<%= item.title %>](<%= item.url %>) (<%= item.name %>) 5 | <% if (item.overview) { %> 6 | ><%= item.overview %> 7 | <% } %> 8 | <% } %> -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-blogs-collector", 3 | "version": "1.0.1", 4 | "description": "Collector for blogs in github", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "node ./src/build.js", 8 | "harvest": "node ./src/harvest-bootstrap.js" 9 | }, 10 | "author": "Tingzhao Yu", 11 | "license": "ISC", 12 | "dependencies": { 13 | "moment": "~2.10.6", 14 | "sync-request": "~2.1.0", 15 | "underscore": "~1.8.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /_README.md: -------------------------------------------------------------------------------- 1 | GITHUB-BLOGS 收集GITHUB上的博客 2 | === 3 | 4 | **watching [github-blogs-weekly](https://github.com/yutingzhao1991/github-blogs-weekly) 就可以获得每周推送** 5 | 6 | **watching [github-blogs-daily](https://github.com/yutingzhao1991/github-blogs-daily) 就可以获得每天推送** 7 | 8 | 自动收集GITHUB上用ISSUES写的博客,当前的推送方式是每周日会新建一个[ISSUE](https://github.com/yutingzhao1991/github-blogs-weekly/labels/Articles)将之前一周的更新博客整理到一起。 9 | 10 | 建议watching [github-blogs-weekly](https://github.com/yutingzhao1991/github-blogs-weekly) 获取博客更新,保证能够获取到更新的同时减少干扰。如果你对某个博客感兴趣,建议star以鼓励作者。 11 | 12 | 如果您的blog不在下面列表中,或者发现有不合理的repo在下面列表中,欢迎提交pr修改 `config.js`。 13 | 修改完成之后请允许 `npm run build yourgithubusername yourgithubpassword` 更新readme 14 | 15 | 博客列表 16 | --- 17 | 18 | {BLOGS_LIST} 19 | 20 | License 21 | --- 22 | 23 | ISC 24 | -------------------------------------------------------------------------------- /src/harvest-bootstrap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // 启动收割 4 | // 抓取时间默认范围为上周创建。 5 | // Usage: node harvest-bootstrap.js githubusername githubpassword type 6 | 7 | var moment = require('moment') 8 | var config = require('../config') 9 | 10 | if (process.argv.length < 5) { 11 | console.log(process.argv) 12 | console.error('Lack argvs.') 13 | process.exit(1) 14 | } 15 | 16 | var username = process.argv[2] 17 | var password = process.argv[3] 18 | // 要将更新发布的repo名称 更新会以创建一个issue的方式发布 19 | var type = process.argv[4] 20 | var startDate, endDate, publishRepo 21 | 22 | if (type == 'daily') { 23 | publishRepo = config.dailyReminderName 24 | startDate = endDate = moment().add(-1, 'days').format('YYYY-MM-DD') 25 | } else { 26 | // weekly 27 | publishRepo = config.weeklyReminderName 28 | startDate = moment().add(-1, 'weeks').startOf('week').format('YYYY-MM-DD') 29 | endDate = moment().add(-1, 'weeks').endOf('week').format('YYYY-MM-DD') 30 | } 31 | 32 | var spawn = require('child_process').spawn, 33 | cmd = spawn('node', [__dirname + '/harvest.js', username, password, startDate, endDate, publishRepo]) 34 | 35 | cmd.stdout.on('data', function (data) { 36 | console.log('stdout: ' + data) 37 | }) 38 | 39 | cmd.stderr.on('data', function (data) { 40 | console.log('stderr: ' + data) 41 | }) 42 | 43 | cmd.on('close', function (code) { 44 | console.log('harvest child process exited with code ' + code) 45 | }) -------------------------------------------------------------------------------- /src/build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Query blogs detail and write to README.md 4 | // Usage: node build.js githubusername githubpassword 5 | 6 | var fs = require('fs') 7 | var _ = require('underscore') 8 | // 为了防止请求限制超过github上限,所有请求同步串行发出。同时也让代码更加简单易懂。 9 | var request = require('sync-request') 10 | var config = require('../config') 11 | 12 | if (process.argv.length < 4) { 13 | console.log(process.argv) 14 | console.error('Not find username and password, use with :" node build.js username password ".') 15 | process.exit(1) 16 | } 17 | 18 | var username = process.argv[2] 19 | var password = process.argv[3] 20 | 21 | console.log('start build ...') 22 | build() 23 | console.log('done!') 24 | 25 | function build() { 26 | var list = generateBlogsInfo(config.repos) 27 | writeResult(list) 28 | } 29 | 30 | function generateBlogsInfo(repos) { 31 | var list = [] 32 | // 添加指定的blog的repo,从第0个开始递归添加. 33 | for (var i = 0; i < repos.length; i++) { 34 | var fullName = repos[i] 35 | console.log('Get detail of repo: ' + fullName) 36 | var url = 'https://api.github.com/repos/' + fullName 37 | var res = request('GET', url, { 38 | headers: { 39 | 'authorization': 'Basic ' + new Buffer(username + ':' + password, 'ascii').toString('base64'), 40 | 'User-Agent': username 41 | } 42 | }) 43 | var data = JSON.parse(res.getBody()) 44 | list.push(data) 45 | } 46 | return list 47 | } 48 | 49 | function writeResult(list) { 50 | // 将最后得到的blog列表写入到blog.json和readme 51 | var blogs = list.map(function(item) { 52 | return { 53 | full_name: item.full_name, 54 | open_issues_count: item.open_issues_count, 55 | html_url: item.html_url, 56 | stargazers_count: item.stargazers_count 57 | } 58 | }) 59 | console.log('writing to readme ...') 60 | blogs.sort(function(a, b) { 61 | return b.stargazers_count - a.stargazers_count 62 | }) 63 | var template = '' + fs.readFileSync(__dirname + '/list.md') 64 | var mdHead = '' + fs.readFileSync(__dirname + '/../_README.md') 65 | var md = mdHead.replace('{BLOGS_LIST}', _.template(template)({ 66 | blogs: blogs 67 | })) 68 | fs.writeFileSync(__dirname + '/../README.md', md) 69 | } -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | 'minBodyLength': 200, // 最小字数要求,同时也是概览长度 5 | 6 | 'weeklyReminderName': 'github-blogs-weekly', // 发布周更新的repo名称 7 | 'dailyReminderName': 'github-blogs-daily', // 发布日更新的repo名称 8 | 'reminderIssuesLabel': 'Articles', // 发布更新Issue时添加的label 9 | 10 | // 开放性的repo,对该列表中的repo读取更新时会跳过"本人发布"的限制 11 | 'orgRepos': [ 12 | 'amfe/article', 13 | 'tmallfe/tmallfe.github.io', 14 | 'baixing/FE-Blog', 15 | 'gf-rd/blog' 16 | ], 17 | // Blog list 18 | 'repos': [ 19 | 'fouber/blog', 20 | 'amfe/article', 21 | 'lifesinger/blog', 22 | 'xufei/blog', 23 | 'tmallfe/tmallfe.github.io', 24 | 'cssmagic/blog', 25 | 'kuitos/kuitos.github.io', 26 | 'livoras/blog', 27 | 'yisibl/blog', 28 | 'wintercn/blog', 29 | 'camsong/blog', 30 | 'riskers/blog', 31 | 'coderyi/blog', 32 | 'lukego/blog', 33 | 'hax/hax.github.com', 34 | 'atian25/blog', 35 | 'Lucifier129/Lucifier129.github.io', 36 | 'bh-lay/blog', 37 | 'dfguo/blog', 38 | 'cnsnake11/blog', 39 | 'onface/blog', 40 | 'chyingp/blog', 41 | 'ant-ued/blog', 42 | 'viktorklang/blog', 43 | 'msurguy/blog', 44 | 'SimplyY/blog', 45 | 'matthew-sun/blog', 46 | 'BayesianLogic/blog', 47 | 'niklasfrykholm/blog', 48 | 'enml/blog', 49 | 'tikonen/blog', 50 | 'lcxfs1991/blog', 51 | 'classicemi/blog', 52 | 'rccoder/blog', 53 | 'baixing/FE-Blog', 54 | 'web2hack/blog', 55 | 'bgolub/blog', 56 | 'ruhoh/blog', 57 | 'ccjr/blog', 58 | 'jakubholynet/blog', 59 | 'huangz1990/blog', 60 | 'pixelhandler/blog', 61 | 'ma6174/blog', 62 | 'LearnShare/blog', 63 | '28harishkumar/blog', 64 | 'steveklabnik/blog', 65 | 'ashfurrow/blog', 66 | 'zhiqiang21/blog', 67 | 'wenzhixin/blog', 68 | 'hueitan/blog', 69 | 'mafintosh/blog', 70 | 'ipfs/blog', 71 | 'ljw1004/blog', 72 | 'imsobear/blog', 73 | 'fwon/blog', 74 | 'mominger/blog', 75 | 'zhaoda/blog', 76 | 'zhouwenbin/blog', 77 | 'Gaubee/blog', 78 | 'YIXUNFE/blog', 79 | 'thoughtram/blog', 80 | 'GitbookIO/blog', 81 | 'zwhu/blog', 82 | 'alvarto/blog', 83 | 'xieranmaya/blog', 84 | 'ngot/blog', 85 | 'fxhover/blog', 86 | 'techird/blog', 87 | 'siddontang/blog', 88 | 'serverfireteam/blog', 89 | 'fperez/blog', 90 | 'aui/blog', 91 | 'nathanleclaire/blog', 92 | 'linxz/blog', 93 | 'confidence68/blog', 94 | 'creeperyang/blog', 95 | 'substack/blog', 96 | 'luqin/blog', 97 | 'woto/blog', 98 | 'kerryChen95/blog', 99 | 'sorrycc/blog', 100 | 'josef-jelinek/blog', 101 | 'fredshare/blog', 102 | 'Hiufan/blog', 103 | 'Pearyman/blog', 104 | 'chunpu/blog', 105 | 'qq610540622/blog', 106 | 'arogulin/blog', 107 | 'pimcore-extensions/blog', 108 | 'divarvel/blog', 109 | 'yutingzhao1991/blog', 110 | 'nareix/blog', 111 | 'strikingly/blog', 112 | 'yikebocai/blog', 113 | 'jollen/blog', 114 | 'yegor256/blog', 115 | 'tarekziade/blog', 116 | 'ecomfe/blog', 117 | 'LingyuCoder/blog', 118 | 'madewithlove/blog', 119 | 'lapwinglabs/blog', 120 | 'coneo/blog', 121 | 'lmk123/blog', 122 | 'iocanel/blog', 123 | 'kengonakajima/blog', 124 | 'amilna/blog', 125 | 'fightteam/blog', 126 | 'mishe/blog', 127 | 'bholst/blog', 128 | 'Enome/blog', 129 | 'youngwind/blog', 130 | 'weexteam/article', 131 | 'sorrycc/zaobao' 132 | ] 133 | } 134 | -------------------------------------------------------------------------------- /src/harvest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // 自动抓取新增的博客,并通过issue的形式发布。 4 | // 抓取时间默认范围为上周创建。 5 | // Usage: node harvest.js githubusername githubpassword [start_date] [end_date] [publishrepo]. 6 | 7 | var request = require('sync-request') 8 | var moment = require('moment') 9 | var fs = require('fs') 10 | var _ = require('underscore') 11 | var config = require('../config') 12 | var blogList = config.repos 13 | 14 | console.log('harvest with: ', process.argv) 15 | if (process.argv.length < 6) { 16 | console.error('Lack argvs.') 17 | process.exit(1) 18 | } 19 | 20 | var username = process.argv[2] 21 | var password = process.argv[3] 22 | // 要将更新发布的repo名称 更新会以创建一个issue的方式发布 23 | var startDate = process.argv[4] 24 | var endDate = process.argv[5] 25 | var publishRepo = process.argv[6] 26 | 27 | console.log('start harvest ' + startDate + ' ' + endDate + ' blogs ...') 28 | if (publishRepo) { 29 | console.log('update will be created a issue to repo: ' + publishRepo) 30 | } 31 | harvest() 32 | console.log('done!') 33 | 34 | function harvest() { 35 | var issues = getIssuesFromRepo(blogList) 36 | // process.argv[4] == '1' 是会创建一个issue,否则只会写到本地 37 | generateNewBlogs(issues, publishRepo) 38 | } 39 | 40 | function getIssuesFromRepo(blogList) { 41 | // 抓取ISSUES 42 | var orgReposIndex = _.indexBy(config.orgRepos) 43 | var newIssues = [] 44 | console.log('get blog which post in ' + startDate + ' - ' + endDate) 45 | for (var index = 0; index < blogList.length; index++) { 46 | var repo = blogList[index] 47 | console.log('Start get issues from repo: ' + repo + ' ...') 48 | var url = 'https://api.github.com/repos/' + repo + '/issues?sort=created&direction=desc' 49 | var res = request('GET', url, { 50 | headers: { 51 | 'authorization': 'Basic ' + new Buffer(username + ':' + password, 'ascii').toString('base64'), 52 | 'User-Agent': username 53 | } 54 | }) 55 | var data = JSON.parse(res.getBody()) 56 | for (var i = 0; i < data.length; i ++) { 57 | var item = data[i] 58 | var createdDate = moment(item.created_at).format('YYYY-MM-DD') 59 | if (createdDate <= endDate 60 | && createdDate >= startDate 61 | && item.body 62 | && item.body.length > config.minBodyLength) { 63 | // New one which post at yesterday. 64 | if (orgReposIndex[repo] || item.user.login == repo.split('/')[0]) { 65 | // 为公共repo或者作者本人发布的则加入到推送列表中 66 | console.log('get a article: ' + item.title) 67 | newIssues.push(item) 68 | } 69 | } else if (createdDate < startDate) { 70 | // Too old. 71 | break 72 | } 73 | } 74 | } 75 | return newIssues 76 | } 77 | 78 | function generateNewBlogs(newIssues, publishRepo) { 79 | if (newIssues.length == 0) { 80 | console.log('notfind new articles') 81 | return 82 | } 83 | var template = '' + fs.readFileSync(__dirname + '/new.md') 84 | var date 85 | if (startDate == endDate) { 86 | date = startDate 87 | } else { 88 | date = startDate + ' - ' + endDate 89 | } 90 | var md = _.template(template)({ 91 | items: newIssues.map(function(item) { 92 | return { 93 | title: item.title, 94 | url: item.html_url, 95 | name: item.user.login, 96 | overview: startDate == endDate ? generateOverview(item.body) : null // 只有daily的带上概览 97 | } 98 | }), 99 | date: date 100 | }) 101 | fs.writeFileSync(__dirname + '/../news/' + date + '.md', md) 102 | if (!publishRepo) { 103 | return 104 | } 105 | // Publish new blogs as a issue. 106 | console.log('Publish new article to your issue.') 107 | var url = 'https://api.github.com/repos/' + username + '/' + publishRepo+ '/issues' 108 | request('POST', url, { 109 | json: { 110 | title: '文章更新 [ ' + date + ' ]', 111 | body: md, 112 | labels: [config.reminderIssuesLabel] 113 | }, 114 | headers: { 115 | 'authorization': 'Basic ' + new Buffer(username + ':' + password, 'ascii').toString('base64'), 116 | 'User-Agent': username 117 | } 118 | }) 119 | console.log('Created issue done!') 120 | } 121 | 122 | // 获取文章概览 123 | function generateOverview(body) { 124 | var splits = body.split('\r\n') 125 | var ret = '' 126 | var i = 0 127 | while(ret.length < config.minBodyLength && i < splits.length) { 128 | ret += splits[i].replace(/#/g, '') 129 | i ++ 130 | } 131 | return ret + '...' 132 | } 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GITHUB-BLOGS 收集GITHUB上的博客 2 | === 3 | 4 | **watching [github-blogs-weekly](https://github.com/yutingzhao1991/github-blogs-weekly) 就可以获得每周推送** 5 | 6 | **watching [github-blogs-daily](https://github.com/yutingzhao1991/github-blogs-daily) 就可以获得每天推送** 7 | 8 | 自动收集GITHUB上用ISSUES写的博客,当前的推送方式是每周日会新建一个[ISSUE](https://github.com/yutingzhao1991/github-blogs-weekly/labels/Articles)将之前一周的更新博客整理到一起。 9 | 10 | 建议watching [github-blogs-weekly](https://github.com/yutingzhao1991/github-blogs-weekly) 获取博客更新,保证能够获取到更新的同时减少干扰。如果你对某个博客感兴趣,建议star以鼓励作者。 11 | 12 | 如果您的blog不在下面列表中,或者发现有不合理的repo在下面列表中,欢迎提交pr修改 `config.js`。 13 | 修改完成之后请允许 `npm run build yourgithubusername yourgithubpassword` 更新readme 14 | 15 | 博客列表 16 | --- 17 | 18 | 19 | - [fouber/blog(12)](https://github.com/fouber/blog) ✯16223 20 | 21 | - [amfe/article(29)](https://github.com/amfe/article) ✯6442 22 | 23 | - [xufei/blog(33)](https://github.com/xufei/blog) ✯5875 24 | 25 | - [lifesinger/blog(87)](https://github.com/lifesinger/blog) ✯4518 26 | 27 | - [tmallfe/tmallfe.github.io(37)](https://github.com/tmallfe/tmallfe.github.io) ✯3559 28 | 29 | - [youngwind/blog(112)](https://github.com/youngwind/blog) ✯3115 30 | 31 | - [sorrycc/blog(28)](https://github.com/sorrycc/blog) ✯2255 32 | 33 | - [cssmagic/blog(70)](https://github.com/cssmagic/blog) ✯2243 34 | 35 | - [livoras/blog(12)](https://github.com/livoras/blog) ✯2167 36 | 37 | - [camsong/blog(8)](https://github.com/camsong/blog) ✯1915 38 | 39 | - [lcxfs1991/blog(24)](https://github.com/lcxfs1991/blog) ✯1732 40 | 41 | - [weexteam/article(169)](https://github.com/weexteam/article) ✯1200 42 | 43 | - [creeperyang/blog(31)](https://github.com/creeperyang/blog) ✯1191 44 | 45 | - [riskers/blog(27)](https://github.com/riskers/blog) ✯947 46 | 47 | - [xieranmaya/blog(8)](https://github.com/xieranmaya/blog) ✯905 48 | 49 | - [kuitos/kuitos.github.io(36)](https://github.com/kuitos/kuitos.github.io) ✯876 50 | 51 | - [atian25/blog(16)](https://github.com/atian25/blog) ✯813 52 | 53 | - [cnsnake11/blog(30)](https://github.com/cnsnake11/blog) ✯653 54 | 55 | - [wintercn/blog(9)](https://github.com/wintercn/blog) ✯476 56 | 57 | - [lukego/blog(23)](https://github.com/lukego/blog) ✯469 58 | 59 | - [yisibl/blog(7)](https://github.com/yisibl/blog) ✯452 60 | 61 | - [rccoder/blog(31)](https://github.com/rccoder/blog) ✯383 62 | 63 | - [Lucifier129/Lucifier129.github.io(12)](https://github.com/Lucifier129/Lucifier129.github.io) ✯380 64 | 65 | - [hax/hax.github.com(41)](https://github.com/hax/hax.github.com) ✯373 66 | 67 | - [zhiqiang21/blog(42)](https://github.com/zhiqiang21/blog) ✯333 68 | 69 | - [lmk123/blog(58)](https://github.com/lmk123/blog) ✯294 70 | 71 | - [bh-lay/blog(2)](https://github.com/bh-lay/blog) ✯292 72 | 73 | - [onface/blog(13)](https://github.com/onface/blog) ✯288 74 | 75 | - [chyingp/blog(32)](https://github.com/chyingp/blog) ✯266 76 | 77 | - [fwon/blog(37)](https://github.com/fwon/blog) ✯255 78 | 79 | - [viktorklang/blog(1)](https://github.com/viktorklang/blog) ✯239 80 | 81 | - [mishe/blog(160)](https://github.com/mishe/blog) ✯196 82 | 83 | - [matthew-sun/blog(20)](https://github.com/matthew-sun/blog) ✯189 84 | 85 | - [SimplyY/blog(3)](https://github.com/SimplyY/blog) ✯179 86 | 87 | - [ant-ued/blog(2)](https://github.com/ant-ued/blog) ✯164 88 | 89 | - [huangz1990/blog(0)](https://github.com/huangz1990/blog) ✯152 90 | 91 | - [dfguo/blog(1)](https://github.com/dfguo/blog) ✯131 92 | 93 | - [imsobear/blog(0)](https://github.com/imsobear/blog) ✯126 94 | 95 | - [YIXUNFE/blog(81)](https://github.com/YIXUNFE/blog) ✯121 96 | 97 | - [ma6174/blog(17)](https://github.com/ma6174/blog) ✯108 98 | 99 | - [tikonen/blog(1)](https://github.com/tikonen/blog) ✯95 100 | 101 | - [msurguy/blog(2)](https://github.com/msurguy/blog) ✯94 102 | 103 | - [fredshare/blog(29)](https://github.com/fredshare/blog) ✯90 104 | 105 | - [28harishkumar/blog(4)](https://github.com/28harishkumar/blog) ✯89 106 | 107 | - [enml/blog(5)](https://github.com/enml/blog) ✯88 108 | 109 | - [baixing/FE-Blog(8)](https://github.com/baixing/FE-Blog) ✯86 110 | 111 | - [BayesianLogic/blog(48)](https://github.com/BayesianLogic/blog) ✯84 112 | 113 | - [niklasfrykholm/blog(7)](https://github.com/niklasfrykholm/blog) ✯75 114 | 115 | - [luqin/blog(15)](https://github.com/luqin/blog) ✯71 116 | 117 | - [zhouwenbin/blog(18)](https://github.com/zhouwenbin/blog) ✯70 118 | 119 | - [ipfs/blog(39)](https://github.com/ipfs/blog) ✯67 120 | 121 | - [ashfurrow/blog(1)](https://github.com/ashfurrow/blog) ✯67 122 | 123 | - [confidence68/blog(286)](https://github.com/confidence68/blog) ✯66 124 | 125 | - [web2hack/blog(1)](https://github.com/web2hack/blog) ✯63 126 | 127 | - [zwhu/blog(43)](https://github.com/zwhu/blog) ✯53 128 | 129 | - [ljw1004/blog(3)](https://github.com/ljw1004/blog) ✯51 130 | 131 | - [serverfireteam/blog(20)](https://github.com/serverfireteam/blog) ✯50 132 | 133 | - [Gaubee/blog(32)](https://github.com/Gaubee/blog) ✯50 134 | 135 | - [jollen/blog(24)](https://github.com/jollen/blog) ✯50 136 | 137 | - [LearnShare/blog(1)](https://github.com/LearnShare/blog) ✯50 138 | 139 | - [wenzhixin/blog(6)](https://github.com/wenzhixin/blog) ✯47 140 | 141 | - [sorrycc/zaobao(51)](https://github.com/sorrycc/zaobao) ✯46 142 | 143 | - [bgolub/blog(1)](https://github.com/bgolub/blog) ✯45 144 | 145 | - [ruhoh/blog(10)](https://github.com/ruhoh/blog) ✯44 146 | 147 | - [thoughtram/blog(7)](https://github.com/thoughtram/blog) ✯43 148 | 149 | - [yegor256/blog(9)](https://github.com/yegor256/blog) ✯42 150 | 151 | - [jakubholynet/blog(2)](https://github.com/jakubholynet/blog) ✯41 152 | 153 | - [ccjr/blog(1)](https://github.com/ccjr/blog) ✯40 154 | 155 | - [mominger/blog(18)](https://github.com/mominger/blog) ✯39 156 | 157 | - [hueitan/blog(3)](https://github.com/hueitan/blog) ✯38 158 | 159 | - [techird/blog(2)](https://github.com/techird/blog) ✯38 160 | 161 | - [pixelhandler/blog(0)](https://github.com/pixelhandler/blog) ✯37 162 | 163 | - [fxhover/blog(0)](https://github.com/fxhover/blog) ✯36 164 | 165 | - [steveklabnik/blog(1)](https://github.com/steveklabnik/blog) ✯33 166 | 167 | - [lapwinglabs/blog(2)](https://github.com/lapwinglabs/blog) ✯32 168 | 169 | - [alvarto/blog(6)](https://github.com/alvarto/blog) ✯31 170 | 171 | - [nathanleclaire/blog(7)](https://github.com/nathanleclaire/blog) ✯30 172 | 173 | - [mafintosh/blog(1)](https://github.com/mafintosh/blog) ✯29 174 | 175 | - [yutingzhao1991/blog(5)](https://github.com/yutingzhao1991/blog) ✯27 176 | 177 | - [zhaoda/blog(6)](https://github.com/zhaoda/blog) ✯25 178 | 179 | - [GitbookIO/blog(3)](https://github.com/GitbookIO/blog) ✯24 180 | 181 | - [classicemi/blog(20)](https://github.com/classicemi/blog) ✯23 182 | 183 | - [fperez/blog(0)](https://github.com/fperez/blog) ✯21 184 | 185 | - [substack/blog(4)](https://github.com/substack/blog) ✯21 186 | 187 | - [siddontang/blog(11)](https://github.com/siddontang/blog) ✯20 188 | 189 | - [ngot/blog(2)](https://github.com/ngot/blog) ✯20 190 | 191 | - [nareix/blog(0)](https://github.com/nareix/blog) ✯20 192 | 193 | - [coneo/blog(25)](https://github.com/coneo/blog) ✯20 194 | 195 | - [Hiufan/blog(19)](https://github.com/Hiufan/blog) ✯19 196 | 197 | - [linxz/blog(2)](https://github.com/linxz/blog) ✯19 198 | 199 | - [aui/blog(2)](https://github.com/aui/blog) ✯19 200 | 201 | - [josef-jelinek/blog(1)](https://github.com/josef-jelinek/blog) ✯19 202 | 203 | - [chunpu/blog(71)](https://github.com/chunpu/blog) ✯18 204 | 205 | - [kerryChen95/blog(9)](https://github.com/kerryChen95/blog) ✯16 206 | 207 | - [qq610540622/blog(2)](https://github.com/qq610540622/blog) ✯15 208 | 209 | - [Pearyman/blog(3)](https://github.com/Pearyman/blog) ✯15 210 | 211 | - [divarvel/blog(0)](https://github.com/divarvel/blog) ✯13 212 | 213 | - [yikebocai/blog(40)](https://github.com/yikebocai/blog) ✯13 214 | 215 | - [woto/blog(2)](https://github.com/woto/blog) ✯13 216 | 217 | - [arogulin/blog(10)](https://github.com/arogulin/blog) ✯13 218 | 219 | - [amilna/blog(2)](https://github.com/amilna/blog) ✯11 220 | 221 | - [madewithlove/blog(6)](https://github.com/madewithlove/blog) ✯10 222 | 223 | - [kengonakajima/blog(0)](https://github.com/kengonakajima/blog) ✯10 224 | 225 | - [strikingly/blog(21)](https://github.com/strikingly/blog) ✯10 226 | 227 | - [pimcore-extensions/blog(0)](https://github.com/pimcore-extensions/blog) ✯10 228 | 229 | - [tarekziade/blog(1)](https://github.com/tarekziade/blog) ✯9 230 | 231 | - [LingyuCoder/blog(2)](https://github.com/LingyuCoder/blog) ✯9 232 | 233 | - [iocanel/blog(0)](https://github.com/iocanel/blog) ✯8 234 | 235 | - [ecomfe/blog(3)](https://github.com/ecomfe/blog) ✯8 236 | 237 | - [Enome/blog(4)](https://github.com/Enome/blog) ✯7 238 | 239 | - [fightteam/blog(1)](https://github.com/fightteam/blog) ✯7 240 | 241 | - [bholst/blog(6)](https://github.com/bholst/blog) ✯6 242 | 243 | - [coderyi/blog(0)](https://github.com/coderyi/blog) ✯1 244 | 245 | 246 | License 247 | --- 248 | 249 | ISC 250 | --------------------------------------------------------------------------------