├── .babelrc ├── .eslintrc ├── .gitignore ├── README.md ├── bin └── typer.js ├── config.js ├── index.html ├── lib ├── 404.html ├── index.html ├── typer.c9b74e8e.js └── vendor.c9b74e8e.js ├── package.json ├── server.js ├── src ├── App.js ├── Home.js ├── Post.js ├── api │ └── index.js ├── components │ ├── calendar │ │ ├── Calendar.js │ │ ├── CalendarHeader.js │ │ ├── CalendarPanel.js │ │ ├── CalendarTop.js │ │ ├── CalendarWeek.js │ │ └── calendar.scss │ ├── contents │ │ ├── Content.js │ │ └── content.scss │ └── footer.js ├── styles │ └── main.scss └── template │ ├── 404.ejs │ └── index.ejs ├── webpack.config.dev.js ├── webpack.config.npm.js └── webpack.config.prod.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-0"], 3 | "env" : { 4 | "development": { 5 | "presets": ["react-hmre"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "jsx": true, 4 | "modules": true 5 | }, 6 | "env": { 7 | "browser": true, 8 | "node": true 9 | }, 10 | "parser": "babel-eslint", 11 | "rules" : { 12 | "quotes": [2, "single"], 13 | "strict": [2, "never"], 14 | "babel/generator-star-spacing": 1, 15 | "babel/new-cap": 1, 16 | "babel/object-shorthand": 1, 17 | "babel/arrow-parens": 1, 18 | "babel/no-await-in-loop": 1, 19 | "react/jsx-uses-react": 2, 20 | "react/jsx-uses-vars": 2, 21 | "react/react-in-jsx-scope": 2 22 | }, 23 | "plugins": [ 24 | "babel", 25 | "react" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | npm-debug.log 4 | 5 | !dist/index.html 6 | 7 | config.js 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Typer 2 | 3 | []() 4 | []() 5 | []() 6 | 7 | 8 | 9 | 10 | > A diary generator powered by Github issues && React && React-router. 11 | 12 | ## [Demo](https://stephenlyz.github.io/diary/) 13 |  14 | 15 | ## Usage 16 | 17 | ### 1. Install typer 18 | 19 | `$ (sudo) npm install -g @vueact/typer` 20 | 21 | ### 2. Init folder 22 | 23 | create a folder 24 | 25 | ``` 26 | $ mkdir diary 27 | $ cd diary 28 | $ typer init 29 | ``` 30 | 31 | or 32 | 33 | `$ typer init diary` 34 | 35 | Then you will see the files tree like this: 36 | 37 | ``` 38 | -- diary 39 | -- index.html 40 | -- typer.[hash].js 41 | -- vendor.[hash].js 42 | -- config.yml 43 | -- .gitignore 44 | ``` 45 | 46 | ### 3. Configure 47 | 48 | Modify the `config.yml`: 49 | 50 | ``` 51 | # site title 52 | title: 'Typer' 53 | 54 | # github user's name 55 | user: 'stephenLYao' 56 | 57 | # issue repo, all diary content from here 58 | repo: 'diary' 59 | 60 | # token 61 | token: 62 | 63 | ``` 64 | 65 | **Add access token is up to you, however I suggest to do so.** 66 | 67 | Go to [https://github.com/settings/tokens](https://github.com/settings/tokens) 68 | 69 |  70 | 71 | ### 4. Build 72 | 73 | Run build to generate diary 74 | 75 | `$ typer build` 76 | 77 | ### 5. Deploy 78 | Now push all files to the repo `gh-pages` branch which you modify in the `config.yml`, 79 | and Everything has done, Just have typer :) 80 | 81 | 82 | ## Todo 83 | 84 | - [ ] add theme configure 85 | 86 | 87 | **Very thanks [Mirror](https://github.com/LoeiFy/Mirror)!** 88 | 89 | ## License 90 | MIT 91 | -------------------------------------------------------------------------------- /bin/typer.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | 4 | var program = require('commander') 5 | var path = require('path') 6 | var fs = require('fs-extra') 7 | var yaml = require('yamljs') 8 | 9 | var ignore = '.DS_Store' 10 | var config = '# site title\ntitle:\n\n# github user\nuser:\n\n# issue repo\nrepo:\n\n# token\ntoken:' 11 | 12 | program 13 | .allowUnknownOption() 14 | .usage(' ') 15 | 16 | // display version 17 | program 18 | .command('version') 19 | .description('Typer version is ') 20 | .action(function(){ 21 | console.log(require('../package.json').version) 22 | }) 23 | 24 | // init 25 | program 26 | .command('init [folder]') 27 | .description('Create a diary.') 28 | .action(function(folder) { 29 | folder = folder || '' 30 | var files = [ 31 | { name: '.gitignore', data: ignore }, 32 | { name: 'config.yml', data: config } 33 | ] 34 | fs.copySync(path.join(__dirname, '../lib'), path.join(process.cwd(), folder)) 35 | 36 | files.forEach(function(file) { 37 | var fileName = path.join(process.cwd(), folder, file.name) 38 | if (!fs.existsSync(fileName)) { 39 | fs.outputFileSync(fileName, file.data) 40 | } 41 | }) 42 | 43 | console.log('Successful !! Please modify "config.yml" and then run typer build') 44 | 45 | }) 46 | 47 | // build 48 | program 49 | .command('build') 50 | .description('Build a diary.') 51 | .action(function() { 52 | var config = yaml.load(process.cwd() +'/config.yml') 53 | var html = fs.readFileSync(process.cwd() +'/index.html', 'utf-8') 54 | 55 | if (!config.title || !config.user || !config.repo ) { 56 | return console.log('Please finish your configure information !!') 57 | } 58 | 59 | if (config.token) { 60 | var token = config.token 61 | token = token.replace(/[\r\n]+/g, '') 62 | token = token.charAt(0) +'#'+ token.substr(1) 63 | } 64 | 65 | html = html.replace('$config', JSON.stringify(config)) 66 | html = html.replace(/\$repo/g, config.repo) 67 | fs.outputFileSync(process.cwd() +'/index.html', html) 68 | 69 | console.log('Good ~ Enjoy typer everyday :)') 70 | }) 71 | 72 | program 73 | .parse(process.argv) 74 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | // config 2 | 3 | module.exports = { 4 | 5 | // The title of your diary 6 | title: 'Typer Everyday', 7 | // Your github name 8 | user: 'stephenLYao', 9 | // The github repo where put your diary content 10 | repo: 'diary', 11 | // The token 12 | token: '' 13 | } 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 | Typer 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /lib/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Single Page Apps for GitHub Pages 6 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /lib/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /lib/typer.c9b74e8e.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1],{0:function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var l=function(){function e(e,t){for(var n=0;n=0&&g.splice(t,1)}function l(e){var t=document.createElement("style");return t.type="text/css",a(e,t),t}function c(e){var t=document.createElement("link");return t.rel="stylesheet",a(e,t),t}function d(e,t){var n,o,r;if(t.singleton){var a=w++;n=m||(m=l(t)),o=s.bind(null,n,a,!1),r=s.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=c(t),o=f.bind(null,n),r=function(){i(n),n.href&&URL.revokeObjectURL(n.href)}):(n=l(t),o=u.bind(null,n),r=function(){i(n)});return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else r()}}function s(e,t,n,o){var r=n?"":o.css;if(e.styleSheet)e.styleSheet.cssText=v(t,r);else{var a=document.createTextNode(r),i=e.childNodes;i[t]&&e.removeChild(i[t]),i.length?e.insertBefore(a,i[t]):e.appendChild(a)}}function u(e,t){var n=t.css,o=t.media;if(o&&e.setAttribute("media",o),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}function f(e,t){var n=t.css,o=t.sourceMap;o&&(n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */");var r=new Blob([n],{type:"text/css"}),a=e.href;e.href=URL.createObjectURL(r),a&&URL.revokeObjectURL(a)}var p={},h=function(e){var t;return function(){return"undefined"==typeof t&&(t=e.apply(this,arguments)),t}},y=h(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),b=h(function(){return document.head||document.getElementsByTagName("head")[0]}),m=null,w=0,g=[];e.exports=function(e,t){t=t||{},"undefined"==typeof t.singleton&&(t.singleton=y()),"undefined"==typeof t.insertAt&&(t.insertAt="bottom");var n=r(e);return o(n,t),function(e){for(var a=[],i=0;i>"}.calendar-header .m-prev:before{content:"<"}.calendar-header .m-next:before{content:">"}.calendar-header .content{flex-grow:3;flex-basis:max-content}.calendar-header .content span{margin-right:10px}.calendar-week{flex-grow:1;flex-basis:0;border-bottom:1px solid #ededed;border-top:1px solid #ededed}.calendar-week .cell{color:#5c5c5c}.calendar-top{max-width:400px;max-height:300px;box-shadow:0 0 3px #000;font:normal 15px Helvetica Neue,Helvetica,Arial,sans-serif;min-width:280px;background:linear-gradient(70deg,#212121,#5c5c5c);color:#fff;text-align:center;position:relative;margin:0 auto}.calendar-top p:first-child{font-size:70px;line-height:130px;margin:0}.calendar-top p:nth-child(2){margin-top:-20px;font-size:20px;padding-bottom:30px}.calendar-panel{background:#fff;padding:0 20px 25px}.calendar-panel .date-cell{width:14.28571%;display:inline-block;text-align:center;line-height:2.8rem;font-weight:bolder}.calendar-panel .today{margin:-1px;cursor:pointer;background:none;border:1px solid #ffb3b3}.calendar-panel .button{transition:all .2s ease-out;cursor:pointer;background:#f0eff0}.calendar-panel .button:hover{background:#5c5c5c;color:#fff}',""])},126:function(e,t,n){t=e.exports=n(45)(),t.push([e.id,'.content-container{position:relative;background-color:#fff;border-bottom:1px solid #d9d9d9;-ms-box-shadow:0 1px 6px #ccc;-o-box-shadow:0 1px 6px #ccc;box-shadow:0 1px 6px #ccc;width:816px;min-height:800px;margin:20px auto}.content-container h2{height:auto;margin:0 100px 10px;width:auto;font-size:22.5pt;height:60px;padding-top:90px;border-bottom:1px solid #e9edf1}.markdown-body{font-size:16px;line-height:1.6;padding:0 100px;margin-bottom:50px}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a.absent{color:#c00}.markdown-body a.anchor{bottom:0;cursor:pointer;display:block;left:0;margin-left:-30px;padding-left:30px;position:absolute;top:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{cursor:text;font-weight:700;margin:20px 0 10px;padding:0;position:relative}.markdown-body h1 .mini-icon-link,.markdown-body h2 .mini-icon-link,.markdown-body h3 .mini-icon-link,.markdown-body h4 .mini-icon-link,.markdown-body h5 .mini-icon-link,.markdown-body h6 .mini-icon-link{color:#000;display:none}.markdown-body h1:hover a.anchor,.markdown-body h2:hover a.anchor,.markdown-body h3:hover a.anchor,.markdown-body h4:hover a.anchor,.markdown-body h5:hover a.anchor,.markdown-body h6:hover a.anchor{line-height:1;margin-left:-22px;padding-left:0;text-decoration:none;top:15%}.markdown-body h1:hover a.anchor .mini-icon-link,.markdown-body h2:hover a.anchor .mini-icon-link,.markdown-body h3:hover a.anchor .mini-icon-link,.markdown-body h4:hover a.anchor .mini-icon-link,.markdown-body h5:hover a.anchor .mini-icon-link,.markdown-body h6:hover a.anchor .mini-icon-link{display:inline-block}.markdown-body h1 code,.markdown-body h1 tt,.markdown-body h2 code,.markdown-body h2 tt,.markdown-body h3 code,.markdown-body h3 tt,.markdown-body h4 code,.markdown-body h4 tt,.markdown-body h5 code,.markdown-body h5 tt,.markdown-body h6 code,.markdown-body h6 tt{font-size:inherit}.markdown-body h1{color:#000;font-size:28px}.markdown-body h2{border-bottom:1px solid #ccc;color:#000;font-size:24px}.markdown-body h3{font-size:18px}.markdown-body h4{font-size:16px}.markdown-body h5{font-size:14px}.markdown-body h6{color:#777;font-size:14px}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin:15px 0}.markdown-body hr{background:url("https://a248.e.akamai.net/assets.github.com/assets/primer/markdown/dirty-shade-350cca8f57223ebd53603021b2e670f4f319f1b7.png") repeat-x scroll 0 0 transparent;border:0 none;color:#ccc;height:4px;padding:0}.markdown-body>h1:first-child,.markdown-body>h1:first-child+h2,.markdown-body>h2:first-child,.markdown-body>h3:first-child,.markdown-body>h4:first-child,.markdown-body>h5:first-child,.markdown-body>h6:first-child,.markdown-body a:first-child h1,.markdown-body a:first-child h2,.markdown-body a:first-child h3,.markdown-body a:first-child h4,.markdown-body a:first-child h5,.markdown-body a:first-child h6{margin-top:0;padding-top:0}.markdown-body h1+p,.markdown-body h2+p,.markdown-body h3+p,.markdown-body h4+p,.markdown-body h5+p,.markdown-body h6+p{margin-top:0}.markdown-body li p.first{display:inline-block}.markdown-body ol,.markdown-body ul{padding-left:30px}.markdown-body ol.no-list,.markdown-body ul.no-list{list-style-type:none;padding:0}.markdown-body ol li>:first-child,.markdown-body ul li>:first-child{margin-top:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-bottom:0}.markdown-body dl{padding:0}.markdown-body dl dt{font-size:14px;font-style:italic;font-weight:700;margin:15px 0 5px;padding:0}.markdown-body dl dt:first-child{padding:0}.markdown-body dl dt>:first-child{margin-top:0}.markdown-body dl dt>:last-child{margin-bottom:0}.markdown-body dl dd{margin:0 0 15px;padding:0 15px}.markdown-body dl dd>:first-child{margin-top:0}.markdown-body dl dd>:last-child{margin-bottom:0}.markdown-body blockquote{border-left:4px solid #ddd;color:#777;padding:0 15px}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body table th{font-weight:700}.markdown-body table td,.markdown-body table th{border:1px solid #ccc;padding:6px 13px}.markdown-body table tr{background-color:#fff;border-top:1px solid #ccc}.markdown-body table tr:nth-child(2n){background-color:#f8f8f8}.markdown-body img{max-width:100%}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{border:1px solid #ddd;display:block;float:left;margin:13px 0 0;overflow:hidden;padding:7px;width:auto}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{clear:both;color:#333;display:block;padding:5px 0 0}.markdown-body span.align-center{clear:both;display:block;overflow:hidden}.markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown-body span.align-center span img{margin:0 auto;text-align:center}.markdown-body span.align-right{clear:both;display:block;overflow:hidden}.markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown-body span.align-right span img{margin:0;text-align:right}.markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown-body span.float-left span{margin:13px 0 0}.markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown-body code,.markdown-body tt{background-color:#f8f8f8;border:1px solid #eaeaea;border-radius:3px 3px 3px 3px;margin:0 2px;padding:0 5px;white-space:nowrap}.markdown-body pre>code{background:none repeat scroll 0 0 transparent;border:medium none;margin:0;padding:0;white-space:pre}.markdown-body .highlight pre,.markdown-body pre{background-color:#f8f8f8;border:1px solid #ccc;border-radius:3px 3px 3px 3px;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px}.markdown-body pre code,.markdown-body pre tt{background-color:transparent;border:medium none}',""])},127:function(e,t,n){t=e.exports=n(45)(),t.push([e.id,"body,html{background-color:#f0eff0;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:antialiased}body{font-family:-apple-system,BlinkMacSystemFont,PingFang SC,Helvetica,Tahoma,Arial,Hiragino Sans GB,Microsoft YaHei,微软雅黑,SimSun,宋体,Heiti,黑体,sans-serif;font-size:14px;overflow-x:hidden;overflow-y:scroll;line-height:1;position:relative;word-wrap:break-word}a,body{color:#333}footer{text-align:center}",""])},248:function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var l=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};o(this,e),this.user=t.user,this.repo=t.repo,t.token&&(this.token=t.token)}return r(e,[{key:"listPosts",value:function(t){var n=e.getUrl("/repos/"+this.user+"/"+this.repo+"/issues");return e.request(n,t).then(function(t){return t.map(function(t){return e.convertPost(t)})})}}],[{key:"getUrl",value:function(t,n){var o=e.ROOT+t;return n&&(o=o+"?"+a.stringify(n)),o}},{key:"request",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t;return this.token&&(n.access_token=this.token.split("#").join("")),n.headers=Object.assign({},n.headers,{Accept:"application/vnd.github.v3.html+json"}),fetch(e,n).then(function(e){if(e.status<200||e.status>=300){var t=new Error(e.statusText);throw t.name="GithubRequestError",t.response=e,t}return e}).then(function(e){return e.json()})}},{key:"convertPost",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{id:e.id,number:e.number,title:e.title,html:e.body_html,createdAt:e.created_at}}}]),e}();i.ROOT="https://api.github.com",t.default=i},251:function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var l=function(){function e(e,t){for(var n=0;n0?(e.month=this.state.month-1,e.year=this.state.year):(e.month=11,e.year=this.state.year-1),Object.assign(e,this.calculate.call(null,e.year,e.month)),this.setState(e)}},{key:"yearNext",value:function(){var e={year:this.state.year+1,month:this.state.month};Object.assign(e,this.calculate.call(null,e.year,e.month)),this.setState(e)}},{key:"yearPrev",value:function(){var e={year:this.state.year-1,month:this.state.month};Object.assign(e,this.calculate.call(null,e.year,e.month)),this.setState(e)}},{key:"renderHeader",value:function(){return d.default.createElement(u.default,{monthNames:this.state.monthNames,year:this.state.year,month:this.state.month,monthPrev:this.monthPrev,monthNext:this.monthNext,yearPrev:this.yearPrev,yearNext:this.yearNext})}},{key:"renderWeek",value:function(){return d.default.createElement(p.default,{dayNames:this.state.dayNames})}},{key:"renderPanel",value:function(){return d.default.createElement(y.default,{year:this.state.year,month:this.state.month,firstOfMonth:this.state.firstOfMonth,daysInMonth:this.state.daysInMonth,today:this.state.today,posts:this.props.posts})}},{key:"renderTop",value:function(){return d.default.createElement(m.default,{today:this.state.today,fullDayNames:this.state.fullDayNames})}},{key:"render",value:function(){return d.default.createElement("div",{className:"container"},this.renderTop(),d.default.createElement("div",{className:"calender-cantainer"},this.renderHeader(),this.renderWeek(),this.renderPanel()))}}]),t}(c.Component);t.default=w},252:function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var l=function(){function e(e,t){for(var n=0;n { 45 | this.setState({ 46 | error: false, 47 | loading: false, 48 | posts 49 | }) 50 | }).catch(err => { 51 | this.setState({ 52 | error: true, 53 | loading: false 54 | }) 55 | console.error(err.stack) 56 | }) 57 | } 58 | 59 | render() { 60 | const props = Object.assign({}, this.state, { config: this.props.config }) 61 | return ( 62 | 63 | 64 | { React.cloneElement(this.props.children, props) } 65 | 66 | 67 | ) 68 | } 69 | } 70 | 71 | const router = ( 72 | 73 | 74 | 75 | 76 | 77 | 78 | ) 79 | 80 | render(router, document.getElementById('root')) 81 | -------------------------------------------------------------------------------- /src/Home.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Calendar from './components/calendar/Calendar' 3 | import Footer from './components/footer' 4 | 5 | export default class Home extends Component { 6 | 7 | static propTypes = { 8 | config: React.PropTypes.object, 9 | loading: React.PropTypes.bool, 10 | error: React.PropTypes.bool, 11 | posts: React.PropTypes.array 12 | } 13 | 14 | static defaultProps = { 15 | loading: true, 16 | error: false, 17 | } 18 | 19 | constructor(props) { 20 | super(props) 21 | 22 | } 23 | 24 | componentDidMount() { 25 | document.title = this.props.config.title || 'diary' 26 | } 27 | 28 | 29 | render() { 30 | return ( 31 | 32 | 33 | 34 | 35 | ) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Post.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Content from './components/contents/Content' 3 | import Footer from './components/footer' 4 | export default class Post extends Component { 5 | 6 | static propTypes = { 7 | params: React.PropTypes.object, 8 | posts: React.PropTypes.array, 9 | } 10 | 11 | constructor(props) { 12 | super(props) 13 | 14 | const post = this.fetchPost(props.params.id, props.posts) 15 | this.state = { post } 16 | document.title = post.title || '' 17 | } 18 | 19 | componentWillReceiveProps(nextProps) { 20 | const post = this.fetchPost(nextProps.params.id, nextProps.posts) 21 | this.setState({ post }) 22 | document.title = post.title || '' 23 | } 24 | 25 | fetchPost(postId, posts) { 26 | let post = {} 27 | for (const item of posts) { 28 | if (String(item.id) === postId) { 29 | post = item 30 | } 31 | } 32 | return post 33 | } 34 | 35 | render() { 36 | return ( 37 | 38 | 39 | 40 | 41 | ) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/api/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch' 2 | const qs = require('qs') 3 | 4 | export default class Client { 5 | 6 | static ROOT = 'https://api.github.com' 7 | 8 | constructor(options = {}) { 9 | this.user = options.user 10 | this.repo = options.repo 11 | 12 | if(options.token) { 13 | this.token = options.token 14 | } 15 | } 16 | 17 | static getUrl(url, query) { 18 | let result = Client.ROOT + url 19 | if(query) { 20 | result = result + '?' + qs.stringify(query) 21 | } 22 | return result 23 | } 24 | 25 | static request(url, reqArgs = {}) { 26 | const args = reqArgs 27 | if(this.token) { 28 | args.access_token = this.token.split('#').join('') 29 | } 30 | args.headers = Object.assign({}, args.headers, { 31 | Accept: 'application/vnd.github.v3.html+json' 32 | }) 33 | return fetch(url, args) 34 | .then(res => { 35 | if(res.status < 200 || res.status >= 300) { 36 | const err = new Error(res.statusText) 37 | err.name = 'GithubRequestError' 38 | err.response = res 39 | throw err 40 | } 41 | return res 42 | }) 43 | .then(res => { 44 | return res.json() 45 | }) 46 | } 47 | 48 | static convertPost(post = {}) { 49 | return { 50 | id: post.id, 51 | number: post.number, 52 | title: post.title, 53 | html: post.body_html, 54 | createdAt: post.created_at 55 | } 56 | } 57 | 58 | listPosts(args) { 59 | const url = Client.getUrl(`/repos/${this.user}/${this.repo}/issues`) 60 | return Client.request(url, args).then(data => { 61 | return data.map(item => Client.convertPost(item)) 62 | }) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/components/calendar/Calendar.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | import CalendarHeader from './CalendarHeader' 4 | import CalendarWeek from './CalendarWeek' 5 | import CalendarPanel from './CalendarPanel' 6 | import CalendarTop from './CalendarTop' 7 | 8 | import './calendar.scss' 9 | 10 | export default class Calendar extends Component { 11 | constructor(props) { 12 | super(props) 13 | 14 | const date = new Date() 15 | 16 | this.state = { 17 | year: date.getFullYear(), 18 | month: date.getMonth(), 19 | dayNames: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], 20 | fullDayNames: ['Sunday','Monday','TuesDay','Wednesday','Thursday','Friday','Saturday'], 21 | monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], 22 | firstOfMonth: null, 23 | daysInMonth: null, 24 | today: date.getDate() 25 | } 26 | 27 | this.monthNext = this.monthNext.bind(this) 28 | this.monthPrev = this.monthPrev.bind(this) 29 | 30 | this.yearNext = this.yearNext.bind(this) 31 | this.yearPrev = this.yearPrev.bind(this) 32 | 33 | } 34 | 35 | componentWillMount() { 36 | this.setState(this.calculate.call(null,this.state.year,this.state.month)) 37 | } 38 | calculate(year,month) { 39 | return { 40 | firstOfMonth: new Date(year,month,1).getDay(), 41 | daysInMonth: new Date(year,month + 1,0).getDate() 42 | } 43 | } 44 | 45 | monthNext() { 46 | const state = {} 47 | if(this.state.month < 11) { 48 | state.month = this.state.month + 1 49 | state.year = this.state.year 50 | } else { 51 | state.month = 0 52 | state.year = this.state.year + 1 53 | } 54 | Object.assign(state,this.calculate.call(null, state.year, state.month)) 55 | this.setState(state) 56 | } 57 | 58 | monthPrev() { 59 | const state = {} 60 | if(this.state.month > 0) { 61 | state.month = this.state.month - 1 62 | state.year = this.state.year 63 | } else { 64 | state.month = 11 65 | state.year = this.state.year - 1 66 | } 67 | Object.assign(state,this.calculate.call(null, state.year, state.month)) 68 | this.setState(state) 69 | } 70 | 71 | yearNext() { 72 | const state = { 73 | year: this.state.year + 1, 74 | month: this.state.month 75 | } 76 | Object.assign(state,this.calculate.call(null, state.year, state.month)) 77 | this.setState(state) 78 | } 79 | 80 | yearPrev() { 81 | const state = { 82 | year: this.state.year - 1, 83 | month: this.state.month 84 | } 85 | Object.assign(state,this.calculate.call(null, state.year, state.month)) 86 | this.setState(state) 87 | } 88 | 89 | renderHeader() { 90 | return ( 91 | 100 | ) 101 | } 102 | 103 | renderWeek() { 104 | return ( 105 | 108 | ) 109 | 110 | } 111 | 112 | renderPanel() { 113 | return ( 114 | 122 | ) 123 | } 124 | 125 | renderTop() { 126 | return ( 127 | 131 | ) 132 | } 133 | render() { 134 | return ( 135 | 136 | {this.renderTop()} 137 | 138 | {this.renderHeader()} 139 | {this.renderWeek()} 140 | {this.renderPanel()} 141 | 142 | 143 | ) 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/components/calendar/CalendarHeader.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class CalendarHeader extends Component { 4 | constructor(props) { 5 | super(props) 6 | } 7 | 8 | render() { 9 | const { monthNames,year,month,monthPrev,monthNext,yearPrev,yearNext } = this.props 10 | return ( 11 | 12 | 13 | 14 | 15 | {monthNames[month]} 16 | {year} 17 | 18 | 19 | 20 | 21 | ) 22 | } 23 | } -------------------------------------------------------------------------------- /src/components/calendar/CalendarPanel.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Link } from 'react-router' 3 | 4 | export default class CalendarPanel extends Component { 5 | constructor(props) { 6 | super(props) 7 | } 8 | 9 | postTimeFormat(post) { 10 | const time = post.createdAt.split('T')[0] 11 | return { 12 | postYear: time.split('-')[0], 13 | postMonth: time.split('-')[1], 14 | postDay: time.split('-')[2] 15 | } 16 | } 17 | 18 | renderOffset() { 19 | const {firstOfMonth} = this.props 20 | const offsetArray = [] 21 | 22 | 23 | for (let i = 0 ; i < firstOfMonth; i++) { 24 | offsetArray[i] = i 25 | } 26 | 27 | return offsetArray.map((item,i) => { 28 | return ( 29 | 30 | ) 31 | }) 32 | 33 | } 34 | 35 | renderDays() { 36 | const { daysInMonth,today,month,year,posts } = this.props 37 | const _month = new Date().getMonth() 38 | const _year = new Date().getFullYear() 39 | let dayArray = [] 40 | let postIds = [] 41 | let postTimes = posts.map(post => this.postTimeFormat(post)) 42 | let isAbled = false 43 | 44 | for (let i = 0 ; i < daysInMonth; i++) { 45 | dayArray[i] = i + 1 46 | } 47 | 48 | return dayArray.map((item, i) => { 49 | 50 | isAbled = false 51 | 52 | for(let i = 0;i < postTimes.length;i++){ 53 | if(postTimes[i].postDay == item && postTimes[i].postYear == year && postTimes[i].postMonth-1 == month){ 54 | isAbled = true 55 | postIds[item] = posts[i].id 56 | break 57 | } 58 | } 59 | 60 | if(isAbled && _year === year && _month === month && item === today ) { 61 | return ( 62 | 63 | {item} 64 | 65 | ) 66 | } else if( isAbled ) { 67 | return ( 68 | 69 | {item} 70 | 71 | ) 72 | } else if( _year === year && _month === month && item === today ){ 73 | return ({item}) 74 | } else { 75 | return ( {item} ) 76 | } 77 | }) 78 | 79 | } 80 | 81 | render() { 82 | return ( 83 | 84 | {this.renderOffset()} 85 | {this.renderDays()} 86 | 87 | ) 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/components/calendar/CalendarTop.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class CalendarTop extends Component { 4 | constructor(props) { 5 | super(props) 6 | } 7 | 8 | getWeekDay(year, month, day) { 9 | return new Date(year, month, day).getDay() 10 | } 11 | 12 | render() { 13 | const { today, fullDayNames } = this.props 14 | const _month = new Date().getMonth() 15 | const _year = new Date().getFullYear() 16 | const dayNum = this.getWeekDay(_year, _month, today) 17 | 18 | return ( 19 | 20 | { today } 21 | { fullDayNames[dayNum] } 22 | 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/components/calendar/CalendarWeek.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class CalendarWeek extends Component { 4 | constructor(props) { 5 | super(props) 6 | } 7 | 8 | render() { 9 | const { dayNames } = this.props 10 | return ( 11 | 12 | {dayNames.map((item,i) => { 13 | return ( 14 | 15 | {item} 16 | 17 | ) 18 | })} 19 | 20 | ) 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/components/calendar/calendar.scss: -------------------------------------------------------------------------------- 1 | 2 | .container { 3 | margin: 40px ; 4 | } 5 | 6 | .calender-cantainer { 7 | max-width: 400px; 8 | max-height: 600px; 9 | margin: 0 auto; 10 | background-color: hsl(0, 0%, 100%); 11 | 12 | -moz-box-shadow: 0 0 5px #ccc; 13 | -webkit-box-shadow: 0 0 5px #ccc; 14 | box-shadow: 0 0 5px #ccc; 15 | font: normal 15px Helvetica Neue, Helvetica, Arial, sans-serif; 16 | min-width: 280px; 17 | 18 | .row { 19 | display: flex; 20 | flex-flow: row nowrap; 21 | width: 90%; 22 | justify-content: center; 23 | padding: 0 20px; 24 | } 25 | 26 | .cell { 27 | background-color: #ffffff; 28 | align-items: center; 29 | display: flex; 30 | flex-flow: row nowrap; 31 | flex-grow: 1; 32 | flex-basis: 0; 33 | justify-content: center; 34 | word-wrap: break-word; 35 | overflow-wrap: break-word; 36 | height: 3rem; 37 | } 38 | } 39 | 40 | 41 | .calendar-header { 42 | flex-grow: 1; 43 | flex-basis: 0; 44 | 45 | .m-prev, .m-next, .y-next, .y-prev{ 46 | background-color: #ffffff; 47 | cursor: pointer; 48 | outline: none; 49 | text-align:center; 50 | } 51 | .m-prev:before, .m-next:before ,.y-next:before, .y-prev:before { 52 | position: relative; 53 | top: 0; 54 | display: inline-block; 55 | width: 1.5em; 56 | height: 1.5em; 57 | } 58 | .y-prev:before { 59 | content: "<<" 60 | } 61 | .y-next:before { 62 | content: ">>"; 63 | } 64 | .m-prev:before { 65 | content: "<" 66 | } 67 | .m-next:before { 68 | content: ">"; 69 | } 70 | .content { 71 | flex-grow: 3; 72 | flex-basis: max-content; 73 | 74 | span { 75 | margin-right: 10px; 76 | } 77 | } 78 | } 79 | 80 | .calendar-week { 81 | flex-grow: 1; 82 | flex-basis: 0; 83 | border-bottom: 1px solid hsl(0, 0%, 93%); 84 | border-top: 1px solid hsl(0, 0%, 93%); 85 | .cell { 86 | color: hsl(0, 0%, 36%); 87 | } 88 | } 89 | 90 | .calendar-top { 91 | max-width: 400px; 92 | max-height: 300px; 93 | -moz-box-shadow: 0 0 3px #000; 94 | -webkit-box-shadow: 0 0 3px #000; 95 | box-shadow: 0 0 3px #000; 96 | font: normal 15px Helvetica Neue, Helvetica, Arial, sans-serif; 97 | min-width: 280px; 98 | background: linear-gradient(70deg,hsl(0, 0%, 13%),hsl(0, 0%, 36%)); 99 | color: hsl(0, 0%, 100%); 100 | text-align: center; 101 | position: relative; 102 | margin: 0 auto; 103 | 104 | p:nth-child(1) { 105 | font-size: 70px; 106 | line-height: 130px; 107 | margin: 0; 108 | } 109 | p:nth-child(2) { 110 | margin-top: -20px; 111 | font-size: 20px; 112 | padding-bottom: 30px; 113 | } 114 | } 115 | 116 | .calendar-panel { 117 | background: hsl(0, 0%, 100%); 118 | padding: 0 20px 25px; 119 | .date-cell { 120 | width: calc(100% / 7); 121 | display: inline-block; 122 | text-align: center; 123 | line-height: 2.8rem; 124 | font-weight: bolder; 125 | } 126 | .today { 127 | margin: -1px; 128 | cursor: pointer; 129 | background: none; 130 | border: 1px solid hsl(0, 100%, 85%); 131 | } 132 | .button { 133 | transition: all .2s ease-out; 134 | cursor: pointer; 135 | background: hsl(300, 3%, 94%);; 136 | 137 | &:hover { 138 | background: hsl(0, 0%, 36%); 139 | color: hsl(0, 0%, 100%); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/components/contents/Content.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | import './content.scss' 4 | 5 | export default class Content extends Component { 6 | static propTypes = { 7 | post: React.PropTypes.object 8 | } 9 | 10 | constructor(props) { 11 | super(props); 12 | } 13 | 14 | render() { 15 | const { post } = this.props 16 | console.log(post) 17 | return ( 18 | 19 | { post.title } 20 | 21 | 22 | ) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/components/contents/content.scss: -------------------------------------------------------------------------------- 1 | .content-container { 2 | position: relative; 3 | background-color: hsl(0, 0%, 100%); 4 | border-bottom: 1px solid hsl(0, 0%, 85%); 5 | -webkit-box-shadow: 0px 1px 6px #ccc; 6 | -moz-box-shadow: 0px 1px 6px #ccc; 7 | -ms-box-shadow: 0px 1px 6px #ccc; 8 | -o-box-shadow: 0px 1px 6px #ccc; 9 | box-shadow: 0px 1px 6px #ccc; 10 | width: 816px; 11 | min-height: 800px; 12 | margin: 20px auto; 13 | 14 | h2 { 15 | height: auto; 16 | margin: 0 100px 10px; 17 | width: auto; 18 | font-size: 22.5pt; 19 | height: 60px; 20 | padding-top: 90px; 21 | 22 | border-bottom: 1px solid hsl(213, 24%, 93%); 23 | } 24 | 25 | } 26 | // github markdown样式 27 | .markdown-body { 28 | font-size: 16px; 29 | line-height: 1.6; 30 | padding: 0 100px; 31 | margin-bottom: 50px; 32 | } 33 | .markdown-body > *:first-child { 34 | margin-top: 0 !important; 35 | } 36 | .markdown-body > *:last-child { 37 | margin-bottom: 0 !important; 38 | } 39 | .markdown-body a.absent { 40 | color: #CC0000; 41 | } 42 | .markdown-body a.anchor { 43 | bottom: 0; 44 | cursor: pointer; 45 | display: block; 46 | left: 0; 47 | margin-left: -30px; 48 | padding-left: 30px; 49 | position: absolute; 50 | top: 0; 51 | } 52 | .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { 53 | cursor: text; 54 | font-weight: bold; 55 | margin: 20px 0 10px; 56 | padding: 0; 57 | position: relative; 58 | } 59 | .markdown-body h1 .mini-icon-link, .markdown-body h2 .mini-icon-link, .markdown-body h3 .mini-icon-link, .markdown-body h4 .mini-icon-link, .markdown-body h5 .mini-icon-link, .markdown-body h6 .mini-icon-link { 60 | color: #000000; 61 | display: none; 62 | } 63 | .markdown-body h1:hover a.anchor, .markdown-body h2:hover a.anchor, .markdown-body h3:hover a.anchor, .markdown-body h4:hover a.anchor, .markdown-body h5:hover a.anchor, .markdown-body h6:hover a.anchor { 64 | line-height: 1; 65 | margin-left: -22px; 66 | padding-left: 0; 67 | text-decoration: none; 68 | top: 15%; 69 | } 70 | .markdown-body h1:hover a.anchor .mini-icon-link, .markdown-body h2:hover a.anchor .mini-icon-link, .markdown-body h3:hover a.anchor .mini-icon-link, .markdown-body h4:hover a.anchor .mini-icon-link, .markdown-body h5:hover a.anchor .mini-icon-link, .markdown-body h6:hover a.anchor .mini-icon-link { 71 | display: inline-block; 72 | } 73 | .markdown-body h1 tt, .markdown-body h1 code, .markdown-body h2 tt, .markdown-body h2 code, .markdown-body h3 tt, .markdown-body h3 code, .markdown-body h4 tt, .markdown-body h4 code, .markdown-body h5 tt, .markdown-body h5 code, .markdown-body h6 tt, .markdown-body h6 code { 74 | font-size: inherit; 75 | } 76 | .markdown-body h1 { 77 | color: #000000; 78 | font-size: 28px; 79 | } 80 | .markdown-body h2 { 81 | border-bottom: 1px solid #CCCCCC; 82 | color: #000000; 83 | font-size: 24px; 84 | } 85 | .markdown-body h3 { 86 | font-size: 18px; 87 | } 88 | .markdown-body h4 { 89 | font-size: 16px; 90 | } 91 | .markdown-body h5 { 92 | font-size: 14px; 93 | } 94 | .markdown-body h6 { 95 | color: #777777; 96 | font-size: 14px; 97 | } 98 | .markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre { 99 | margin: 15px 0; 100 | } 101 | .markdown-body hr { 102 | background: url("https://a248.e.akamai.net/assets.github.com/assets/primer/markdown/dirty-shade-350cca8f57223ebd53603021b2e670f4f319f1b7.png") repeat-x scroll 0 0 transparent; 103 | border: 0 none; 104 | color: #CCCCCC; 105 | height: 4px; 106 | padding: 0; 107 | } 108 | .markdown-body > h2:first-child, .markdown-body > h1:first-child, .markdown-body > h1:first-child + h2, .markdown-body > h3:first-child, .markdown-body > h4:first-child, .markdown-body > h5:first-child, .markdown-body > h6:first-child { 109 | margin-top: 0; 110 | padding-top: 0; 111 | } 112 | .markdown-body a:first-child h1, .markdown-body a:first-child h2, .markdown-body a:first-child h3, .markdown-body a:first-child h4, .markdown-body a:first-child h5, .markdown-body a:first-child h6 { 113 | margin-top: 0; 114 | padding-top: 0; 115 | } 116 | .markdown-body h1 + p, .markdown-body h2 + p, .markdown-body h3 + p, .markdown-body h4 + p, .markdown-body h5 + p, .markdown-body h6 + p { 117 | margin-top: 0; 118 | } 119 | .markdown-body li p.first { 120 | display: inline-block; 121 | } 122 | .markdown-body ul, .markdown-body ol { 123 | padding-left: 30px; 124 | } 125 | .markdown-body ul.no-list, .markdown-body ol.no-list { 126 | list-style-type: none; 127 | padding: 0; 128 | } 129 | .markdown-body ul li > *:first-child, .markdown-body ol li > *:first-child { 130 | margin-top: 0; 131 | } 132 | .markdown-body ul ul, .markdown-body ul ol, .markdown-body ol ol, .markdown-body ol ul { 133 | margin-bottom: 0; 134 | } 135 | .markdown-body dl { 136 | padding: 0; 137 | } 138 | .markdown-body dl dt { 139 | font-size: 14px; 140 | font-style: italic; 141 | font-weight: bold; 142 | margin: 15px 0 5px; 143 | padding: 0; 144 | } 145 | .markdown-body dl dt:first-child { 146 | padding: 0; 147 | } 148 | .markdown-body dl dt > *:first-child { 149 | margin-top: 0; 150 | } 151 | .markdown-body dl dt > *:last-child { 152 | margin-bottom: 0; 153 | } 154 | .markdown-body dl dd { 155 | margin: 0 0 15px; 156 | padding: 0 15px; 157 | } 158 | .markdown-body dl dd > *:first-child { 159 | margin-top: 0; 160 | } 161 | .markdown-body dl dd > *:last-child { 162 | margin-bottom: 0; 163 | } 164 | .markdown-body blockquote { 165 | border-left: 4px solid #DDDDDD; 166 | color: #777777; 167 | padding: 0 15px; 168 | } 169 | .markdown-body blockquote > *:first-child { 170 | margin-top: 0; 171 | } 172 | .markdown-body blockquote > *:last-child { 173 | margin-bottom: 0; 174 | } 175 | .markdown-body table th { 176 | font-weight: bold; 177 | } 178 | .markdown-body table th, .markdown-body table td { 179 | border: 1px solid #CCCCCC; 180 | padding: 6px 13px; 181 | } 182 | .markdown-body table tr { 183 | background-color: #FFFFFF; 184 | border-top: 1px solid #CCCCCC; 185 | } 186 | .markdown-body table tr:nth-child(2n) { 187 | background-color: #F8F8F8; 188 | } 189 | .markdown-body img { 190 | max-width: 100%; 191 | } 192 | .markdown-body span.frame { 193 | display: block; 194 | overflow: hidden; 195 | } 196 | .markdown-body span.frame > span { 197 | border: 1px solid #DDDDDD; 198 | display: block; 199 | float: left; 200 | margin: 13px 0 0; 201 | overflow: hidden; 202 | padding: 7px; 203 | width: auto; 204 | } 205 | .markdown-body span.frame span img { 206 | display: block; 207 | float: left; 208 | } 209 | .markdown-body span.frame span span { 210 | clear: both; 211 | color: #333333; 212 | display: block; 213 | padding: 5px 0 0; 214 | } 215 | .markdown-body span.align-center { 216 | clear: both; 217 | display: block; 218 | overflow: hidden; 219 | } 220 | .markdown-body span.align-center > span { 221 | display: block; 222 | margin: 13px auto 0; 223 | overflow: hidden; 224 | text-align: center; 225 | } 226 | .markdown-body span.align-center span img { 227 | margin: 0 auto; 228 | text-align: center; 229 | } 230 | .markdown-body span.align-right { 231 | clear: both; 232 | display: block; 233 | overflow: hidden; 234 | } 235 | .markdown-body span.align-right > span { 236 | display: block; 237 | margin: 13px 0 0; 238 | overflow: hidden; 239 | text-align: right; 240 | } 241 | .markdown-body span.align-right span img { 242 | margin: 0; 243 | text-align: right; 244 | } 245 | .markdown-body span.float-left { 246 | display: block; 247 | float: left; 248 | margin-right: 13px; 249 | overflow: hidden; 250 | } 251 | .markdown-body span.float-left span { 252 | margin: 13px 0 0; 253 | } 254 | .markdown-body span.float-right { 255 | display: block; 256 | float: right; 257 | margin-left: 13px; 258 | overflow: hidden; 259 | } 260 | .markdown-body span.float-right > span { 261 | display: block; 262 | margin: 13px auto 0; 263 | overflow: hidden; 264 | text-align: right; 265 | } 266 | .markdown-body code, .markdown-body tt { 267 | background-color: #F8F8F8; 268 | border: 1px solid #EAEAEA; 269 | border-radius: 3px 3px 3px 3px; 270 | margin: 0 2px; 271 | padding: 0 5px; 272 | white-space: nowrap; 273 | } 274 | .markdown-body pre > code { 275 | background: none repeat scroll 0 0 transparent; 276 | border: medium none; 277 | margin: 0; 278 | padding: 0; 279 | white-space: pre; 280 | } 281 | .markdown-body .highlight pre, .markdown-body pre { 282 | background-color: #F8F8F8; 283 | border: 1px solid #CCCCCC; 284 | border-radius: 3px 3px 3px 3px; 285 | font-size: 13px; 286 | line-height: 19px; 287 | overflow: auto; 288 | padding: 6px 10px; 289 | } 290 | .markdown-body pre code, .markdown-body pre tt { 291 | background-color: transparent; 292 | border: medium none; 293 | } 294 | -------------------------------------------------------------------------------- /src/components/footer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | export default class Footer extends Component { 4 | constructor(props) { 5 | super(props) 6 | } 7 | 8 | render() { 9 | return ( 10 | 13 | ) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/styles/main.scss: -------------------------------------------------------------------------------- 1 | body, html { 2 | background-color: hsl(300, 3%, 94%); 3 | -webkit-tap-highlight-color: hsla(0, 0%, 0%, 0); 4 | -webkit-font-smoothing: antialiased; 5 | } 6 | 7 | body { 8 | font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", Helvetica, Tahoma, Arial, "Hiragino Sans GB", "Microsoft YaHei", 微软雅黑, SimSun, 宋体, Heiti, 黑体, sans-serif; 9 | font-size: 14px; 10 | overflow-x: hidden; 11 | overflow-y: scroll; 12 | line-height: 1; 13 | color: hsl(0, 0%, 20%); 14 | position: relative; 15 | word-wrap: break-word; 16 | } 17 | 18 | a { 19 | color: hsl(0, 0%, 20%); 20 | } 21 | 22 | footer { 23 | text-align: center; 24 | } 25 | -------------------------------------------------------------------------------- /src/template/404.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Single Page Apps for GitHub Pages 6 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/template/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | devtool: "cheap-module-eval-source-map", 7 | entry: { 8 | app: [ 9 | 'webpack-hot-middleware/client', 10 | './src/App' 11 | ], 12 | vendor: ["history", "qs", "react", "react-dom","react-router","whatwg-fetch"] 13 | }, 14 | output: { 15 | path: path.join(__dirname,'dist'), 16 | filename: 'typer.min.js', 17 | publicPath: '/dist/' 18 | }, 19 | module: { 20 | loaders: [ 21 | { 22 | test: /\.js[x]?$/, 23 | loader: 'babel', 24 | exclude: /node_modules/ 25 | }, 26 | { 27 | test: /\.scss$/, 28 | exclude: /node_modules/, 29 | loader: 'style!css!sass' 30 | } 31 | ], 32 | }, 33 | resolve: { 34 | extensions: ['', '.js','.jsx', '.scss'] 35 | }, 36 | plugins: [ 37 | new webpack.HotModuleReplacementPlugin(), 38 | new webpack.NoErrorsPlugin(), 39 | new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.bundle.js"), 40 | new webpack.optimize.UglifyJsPlugin({ 41 | sourceMap: true, 42 | warning: false, 43 | }) 44 | ] 45 | 46 | } 47 | -------------------------------------------------------------------------------- /webpack.config.npm.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | const config = '$config' 6 | const repo = '$repo' 7 | 8 | module.exports = { 9 | entry: { 10 | app: './src/App', 11 | vendor: ["history", "qs", "react", "react-dom","react-router","whatwg-fetch"] 12 | }, 13 | output: { 14 | path: path.join(__dirname, 'lib'), 15 | filename: 'typer.[hash:8].js', 16 | publicPath: `/${repo}` 17 | }, 18 | module: { 19 | loaders: [ 20 | { 21 | test: /\.js[x]?$/, 22 | loader: 'babel', 23 | exclude: /node_modules/ 24 | }, 25 | { 26 | test: /\.scss$/, 27 | exclude: /node_modules/, 28 | loader: 'style!css!sass' 29 | } 30 | ], 31 | }, 32 | resolve: { 33 | extensions: ['', '.js', '.jsx','.scss'] 34 | }, 35 | plugins: [ 36 | new webpack.optimize.OccurrenceOrderPlugin(), 37 | new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.[hash:8].js"), 38 | new webpack.optimize.UglifyJsPlugin({ 39 | compressor: { 40 | warnings: false 41 | } 42 | }), 43 | new HtmlWebpackPlugin({ 44 | title: config.title, 45 | filename: 'index.html', 46 | template: './src/template/index.ejs', 47 | config: config, 48 | inject: 'body', 49 | hash: false 50 | }), 51 | new HtmlWebpackPlugin({ 52 | filename: '404.html', 53 | template: './src/template/404.ejs', 54 | inject: false 55 | }) 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | const config = require('./config.js') 5 | const _config = JSON.stringify(config) 6 | 7 | console.log(config) 8 | module.exports = { 9 | entry: { 10 | app: './src/App', 11 | vendor: ["history", "qs", "react", "react-dom","react-router","whatwg-fetch"] 12 | }, 13 | output: { 14 | path: path.join(__dirname, 'lib'), 15 | filename: 'typer.[hash:8].js', 16 | publicPath: `/${config.repo}` 17 | }, 18 | module: { 19 | loaders: [ 20 | { 21 | test: /\.js[x]?$/, 22 | loader: 'babel', 23 | exclude: /node_modules/ 24 | }, 25 | { 26 | test: /\.scss$/, 27 | exclude: /node_modules/, 28 | loader: 'style!css!sass' 29 | } 30 | ], 31 | }, 32 | resolve: { 33 | extensions: ['', '.js', '.jsx','.scss'] 34 | }, 35 | plugins: [ 36 | new webpack.optimize.OccurrenceOrderPlugin(), 37 | new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.[hash:8].js"), 38 | new webpack.DefinePlugin({ 39 | 'process.env': { 40 | 'NODE_ENV': JSON.stringify('production') 41 | } 42 | }), 43 | new webpack.optimize.UglifyJsPlugin({ 44 | compressor: { 45 | warnings: false 46 | } 47 | }), 48 | new HtmlWebpackPlugin({ 49 | title: 'typer', 50 | filename: 'index.html', 51 | template: './src/template/index.ejs', 52 | config: _config, 53 | inject: 'body', 54 | hash: false 55 | }), 56 | new HtmlWebpackPlugin({ 57 | filename: '404.html', 58 | template: './src/template/404.ejs', 59 | inject: false 60 | }) 61 | ] 62 | } 63 | --------------------------------------------------------------------------------
{ today }
{ fullDayNames[dayNum] }