├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── dist ├── 2.html ├── 404.html ├── about.html ├── assets │ ├── fonts │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── img │ │ ├── favicon.png │ │ └── fontawesome-webfont.svg │ ├── main.css │ ├── main.js │ └── vendors.js ├── category │ ├── bug.html │ ├── duplicate.html │ ├── enhancement.html │ ├── help-wanted.html │ ├── invalid.html │ ├── question.html │ └── wontfix.html ├── feed.xml ├── index.html ├── posts │ ├── exception-handling-for-_configyml.html │ ├── issue-with-using-githubauth-and-firebase.html │ ├── npm-run-push-fails-sometimes.html │ ├── readme-improvements-and-questions.html │ └── you-need-to-set-processnode_env-in-every-script.html ├── standalone.html └── work.html ├── docs └── WritngThemes.md ├── package.json ├── postcss.config.js ├── scripts ├── dev.js ├── generate.js ├── help.js ├── init.js ├── newdraft.js ├── newtheme.js ├── nunjucks_config.js ├── offline.js ├── push.js ├── themefiles │ ├── _config.yml │ ├── category_page.html │ ├── feed.xml │ ├── index.html │ ├── pages │ │ ├── 404.html │ │ ├── about.html │ │ ├── index.html │ │ ├── standalone.html │ │ └── work.html │ ├── post_page.html │ ├── snippets │ │ ├── base.html │ │ ├── comment.html │ │ ├── footer.html │ │ ├── navbar.html │ │ ├── pagination.html │ │ └── post_bottom_navigation.html │ └── static │ │ ├── css │ │ ├── main.scss │ │ └── prism.css │ │ ├── images │ │ ├── favicon.png │ │ ├── gravatar_wrapper.png │ │ └── touch-icon.png │ │ └── js │ │ ├── main.js │ │ ├── prism.js │ │ ├── services.js │ │ └── utils.js ├── upload.js └── utils.js ├── themes ├── default-plain │ ├── _config.yml │ ├── category_page.html │ ├── feed.xml │ ├── index.html │ ├── pages │ │ ├── 404.html │ │ ├── about.html │ │ ├── index.html │ │ ├── standalone.html │ │ └── work.html │ ├── post_page.html │ ├── snippets │ │ ├── base.html │ │ ├── comment.html │ │ ├── footer.html │ │ ├── navbar.html │ │ ├── pagination.html │ │ └── post_bottom_navigation.html │ └── static │ │ ├── css │ │ ├── comments.scss │ │ ├── main.scss │ │ └── prism.css │ │ ├── images │ │ ├── favicon.png │ │ ├── gravatar_wrapper.png │ │ └── touch-icon.png │ │ └── js │ │ ├── main.js │ │ ├── prism.js │ │ ├── services.js │ │ └── utils.js └── leonids-clone │ ├── _config.yml │ ├── category_page.html │ ├── feed.xml │ ├── index.html │ ├── pages │ ├── 404.html │ ├── about.html │ ├── standalone.html │ └── work.html │ ├── post_page.html │ ├── snippets │ ├── base.html │ ├── comment.html │ ├── footer.html │ ├── navbar.html │ ├── pagination.html │ ├── post_bottom_navigation.html │ ├── share_buttons.html │ └── social-links.html │ └── static │ ├── css │ ├── components │ │ ├── _buttons.scss │ │ ├── _global.scss │ │ ├── _grid.scss │ │ ├── _helpers.scss │ │ ├── _mixins.scss │ │ ├── _normalize.scss │ │ ├── _syntax-highlighting.scss │ │ ├── _typography.scss │ │ └── _variables.scss │ ├── font-awesome.min.css │ ├── main.scss │ ├── pages │ │ ├── _archive.scss │ │ ├── _layout.scss │ │ ├── _post.scss │ │ └── _tags.scss │ └── prism.css │ ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 │ ├── images │ ├── favicon.png │ ├── gravatar_wrapper.png │ └── touch-icon.png │ └── js │ ├── main.js │ ├── prism.js │ ├── services.js │ └── utils.js ├── webpack.config.js ├── webpack.dev.js └── webpack.prod.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":[ "es2015" ] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | dev 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Hrishikesh Barman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | blog_name: gitpushblog issue blog 3 | blog_theme: 'leonids-clone' 4 | blog_description: 'a blog with all the open issues from gitpushblog' # optional 5 | domain: 'geekodour.github.io' # optional, username.github.io or if you use a custom domain then that. 6 | engine: nunjucks # optional 7 | userpage: false # is the blog to be hosted in username.github.io ? 8 | baseurl: gitpushblog # [repository name], if userpage is set to true than baseurl will be ignored because it will be "" anyways. 9 | 10 | username: geekodour 11 | author: geekodour # [username of author] 12 | repo: gitpushblog # [repository name], if you're doing this for userpage, this this will be the repository name username.github.io 13 | 14 | posts_per_page: 3 15 | comments_per_page: 3 16 | 17 | comment: 18 | disabled: false 19 | isGithub: true # existing github comments will show up under post 20 | isDisqus: false 21 | isGithubAuth: false # if true, comment box appears under posts to comment using the githubapi once authenticated, see issue #74 22 | disqus_id: geekodour # get your disqus_id from disqus.com 23 | 24 | others: 25 | template_cat_posts: true # if set to true, contents of catagory pages will be generated offline, if false then ajax will be used 26 | 27 | # recommended that you DON'T set anything to firebase right now, this is unstable 28 | # disabling firebase also means you should set `isGithubAuth` to false. 29 | # If you still want to test it(it works), then use your firebase credentials 30 | # see issue: https://github.com/geekodour/gitpushblog/issues/74 31 | firebaseConfig: 32 | apiKey: AIzaSyAZSJ1d1Sr9MnTK-__3D8SrwXjjQf6EML4 33 | authDomain: myblog-2b0ba.firebaseapp.com 34 | projectId: myblog-2b0ba 35 | -------------------------------------------------------------------------------- /dist/2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | gitpushblog issue blog 8 | 9 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 |
35 | geekodour 36 | Student 37 | the struggle is real 38 | 56 | 60 |
61 |
62 |
63 |
64 |
65 | 66 |
67 |
68 | 73 |

74 | exception handling for _config.yml 75 |

76 |
77 |
78 |

79 | the `_config.yml` files is fetch from the filesystem, but there's no exception handling in there, if there is error in `_config.yml` the error output is unhelpful. 80 | used lines:... 81 |

82 |
83 |
84 |
85 |
86 | 93 |

94 | README improvements and questions 95 |

96 |
97 |
98 |

99 | please leave comments/questions/suggestions to improve readme here. 100 |

101 |
102 |
103 | 104 | 105 | 111 | 112 | 113 | 117 |
118 |
119 |
120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /dist/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | gitpushblog issue blog 8 | 9 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 |
35 | geekodour 36 | Student 37 | the struggle is real 38 | 56 | 60 |
61 |
62 |
63 |
64 |
65 | 66 |
67 |

not found page

68 | 404 page not found 69 |
70 | 71 | 75 |
76 |
77 |
78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /dist/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | gitpushblog issue blog 8 | 9 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 |
35 | geekodour 36 | Student 37 | the struggle is real 38 | 56 | 60 |
61 |
62 |
63 |
64 |
65 |
66 | 69 | 70 |
71 | I am about page 72 |
73 | 74 | 75 |
76 | 77 | 81 |
82 |
83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /dist/assets/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/dist/assets/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /dist/assets/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/dist/assets/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /dist/assets/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/dist/assets/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /dist/assets/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/dist/assets/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /dist/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/dist/assets/img/favicon.png -------------------------------------------------------------------------------- /dist/category/bug.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bug - 8 | 9 | 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | geekodour 37 | Student 38 | the struggle is real 39 | 57 | 61 |
62 |
63 |
64 |
65 |
66 |

Posts tagged "bug"

67 |
68 | npm run push fails sometimes 69 |
70 | 71 | 72 | 73 | 77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /dist/category/duplicate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | duplicate - 8 | 9 | 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | geekodour 37 | Student 38 | the struggle is real 39 | 57 | 61 |
62 |
63 |
64 |
65 |
66 |

Posts tagged "duplicate"

67 | 68 | 69 | 70 | 74 |
75 |
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /dist/category/enhancement.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | enhancement - 8 | 9 | 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | geekodour 37 | Student 38 | the struggle is real 39 | 57 | 61 |
62 |
63 |
64 |
65 |
66 |

Posts tagged "enhancement"

67 |
68 | You need to set process.NODE_ENV in every script 69 |
70 | 71 | 72 | 73 | 77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /dist/category/help-wanted.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | help wanted - 8 | 9 | 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | geekodour 37 | Student 38 | the struggle is real 39 | 57 | 61 |
62 |
63 |
64 |
65 |
66 |

Posts tagged "help wanted"

67 |
68 | Issue with using githubAuth and firebase 69 |
70 | 71 | 72 | 73 | 77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /dist/category/invalid.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | invalid - 8 | 9 | 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | geekodour 37 | Student 38 | the struggle is real 39 | 57 | 61 |
62 |
63 |
64 |
65 |
66 |

Posts tagged "invalid"

67 | 68 | 69 | 70 | 74 |
75 |
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /dist/category/question.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | question - 8 | 9 | 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | geekodour 37 | Student 38 | the struggle is real 39 | 57 | 61 |
62 |
63 |
64 |
65 |
66 |

Posts tagged "question"

67 |
68 | Issue with using githubAuth and firebase 69 |
70 |
71 | README improvements and questions 72 |
73 | 74 | 75 | 76 | 80 |
81 |
82 |
83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /dist/category/wontfix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | wontfix - 8 | 9 | 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | geekodour 37 | Student 38 | the struggle is real 39 | 57 | 61 |
62 |
63 |
64 |
65 |
66 |

Posts tagged "wontfix"

67 | 68 | 69 | 70 | 74 |
75 |
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /dist/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | gitpushblog issue blog 5 | a blog with all the open issues from gitpushblog 6 | /gitpushblog 7 | 8 | npm run push fails sometimes 9 | 10 | 2017-07-28T16:21:52Z 11 | /gitpushblog/posts/npm-run-push-fails-sometimes 12 | 13 | 14 | You need to set process.NODE_ENV in every script 15 | 16 | 2017-07-28T14:12:55Z 17 | /gitpushblog/posts/you-need-to-set-processnode_env-in-every-script 18 | 19 | 20 | Issue with using githubAuth and firebase 21 | 22 | 2017-07-28T14:01:58Z 23 | /gitpushblog/posts/issue-with-using-githubauth-and-firebase 24 | 25 | 26 | exception handling for _config.yml 27 | 28 | 2017-07-07T04:28:04Z 29 | /gitpushblog/posts/exception-handling-for-_configyml 30 | 31 | 32 | README improvements and questions 33 | 34 | 2017-06-10T05:30:15Z 35 | /gitpushblog/posts/readme-improvements-and-questions 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /dist/standalone.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | title 12 | 13 | 14 | 15 | 16 | 17 | 18 | I AM SOME TEXT 19 | 20 | 21 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /dist/work.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | gitpushblog issue blog 8 | 9 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 |
35 | geekodour 36 | Student 37 | the struggle is real 38 | 56 | 60 |
61 |
62 |
63 |
64 |
65 | 66 |
67 |

My work

68 |

OpenSource Contributions

69 |

Personal Projects

70 |

Client Work

71 |
72 | 73 | 77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/WritngThemes.md: -------------------------------------------------------------------------------- 1 | # How to write themes for gitpushblog 2 | If you are familiar with HTML and CSS you are good to go. 3 | To create a new theme, run `npm run theme `, boilerplate code will be generated inside `/themes/`, now you can start modifying the theme accordingly. 4 | 5 | You can develop the theme inside gitpushblog's `/theme` directory, but if you want to create separate git repository for the theme, 6 | then to push changes to your theme repository you can do the following after you **add** and **commit** changes to ``. 7 | 8 | `git subtree push --prefix --squash` 9 | 10 | for example you cloned gitpushblog into `` and `` has this theme called **the-plain** inside `/themes` directory, 11 | then you can do the following to push changes to the theme repository. 12 | ``` 13 | $ git subtree push --prefix themes/the-plain https://github.com//the-plain.git master --squash 14 | ``` 15 | 16 | While writing themes, keep in mind if you have a `index.html` inside `/pages` then it will be the homepage and 17 | the `index.html` in the root directory will go inside a directory named `/blog` in the output directory after `npm run dev/generate`, 18 | otherwise the `index.html` in the themes root will be the homepage. 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitpushblog", 3 | "version": "1.0.0", 4 | "description": "a git based blog engine - (using nunjucks)", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node scripts/test.js", 8 | "generate": "npm-run-all clean:dist build:dist webpack:dist", 9 | "dev": "npm-run-all --parallel clean:dev webpack:dev build:dev", 10 | "upload": "node scripts/upload.js", 11 | "draft": "node scripts/newdraft.js", 12 | "theme": "node scripts/newtheme.js", 13 | "help": "node scripts/help.js", 14 | "prepush": "npm run generate", 15 | "push": "node scripts/push.js", 16 | "push:only": "node scripts/push.js", 17 | "build:dev": "node scripts/dev.js", 18 | "build:dist": "node scripts/generate.js", 19 | "webpack:dev": "webpack --env=dev --progress --colors --watch", 20 | "webpack:dev-debug": "webpack --env=dev --progress --colors --watch --display-error-details", 21 | "webpack:dist": "webpack --env=prod --progress --colors", 22 | "clean:dev": "rimraf './dev/*'", 23 | "clean:dist": "rimraf './dist/*'" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/geekodour/gitpushblog.git" 28 | }, 29 | "author": "Hrishikesh Barman (https://geekodour.github.io/)", 30 | "license": "ISC", 31 | "bugs": { 32 | "url": "https://github.com/geekodour/gitpushblog/issues" 33 | }, 34 | "homepage": "https://github.com/geekodour/gitpushblog#readme", 35 | "dependencies": { 36 | "async": "2.5.0", 37 | "autoprefixer": "7.1.1", 38 | "babel-cli": "6.24.1", 39 | "babel-loader": "7.0.0", 40 | "babel-preset-es2015": "6.24.1", 41 | "bulma": "0.4.1", 42 | "chalk": "1.1.3", 43 | "chokidar": "1.7.0", 44 | "clipboard": "1.7.1", 45 | "cp": "0.2.0", 46 | "css-loader": "0.28.2", 47 | "dotenv": "4.0.0", 48 | "extract-text-webpack-plugin": "2.1.0", 49 | "github-blog-api": "1.1.12", 50 | "inquirer": "3.1.1", 51 | "js-yaml": "3.8.4", 52 | "marked": "0.3.6", 53 | "mkdirp": "0.5.1", 54 | "ncp": "2.0.0", 55 | "npm-run-all": "4.0.2", 56 | "nunjucks": "3.0.0", 57 | "ora": "1.2.0", 58 | "postcss-loader": "2.0.5", 59 | "postcss-smart-import": "0.7.2", 60 | "precss": "1.4.0", 61 | "primer-css": "8.0.0", 62 | "pushstate-server": "3.0.0", 63 | "rimraf": "2.6.1", 64 | "sass-loader": "6.0.5", 65 | "slug": "0.9.1", 66 | "style-loader": "0.18.0", 67 | "webpack": "2.6.0", 68 | "yaml-front-matter": "^3.4.0" 69 | }, 70 | "devDependencies": { 71 | "file-loader": "0.11.2", 72 | "url-loader": "0.5.9" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-smart-import')({}), 4 | require('precss')({}), 5 | require('autoprefixer')({}) 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /scripts/dev.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | process.env.NODE_ENV = 'development'; 4 | 5 | const chokidar = require('chokidar'); 6 | const ora = require('ora'); 7 | const server = require('pushstate-server'); 8 | const chalk = require('chalk'); 9 | const mkdirp = require('mkdirp'); 10 | const fs = require('fs'); 11 | const path = require('path'); 12 | 13 | // import configuration files 14 | const init = require('./init'); 15 | const utils = require('./utils.js'); 16 | 17 | // init nunjucks and blog and env variables 18 | const {blog,bc} = init.init(); 19 | const spinner = ora({text:'Fetching posts',spinner:'line'}); 20 | 21 | // initilize some constants 22 | const ROOT_DIR = process.env.ROOT_DIR; 23 | const THEME_DIR = path.join(ROOT_DIR,'themes',bc.meta.blog_theme); 24 | mkdirp.sync(path.join(ROOT_DIR,'drafts')); 25 | const DRAFT_DIR = path.join(ROOT_DIR,'drafts'); 26 | const PORT = 3000; 27 | 28 | // global variables 29 | let posts = []; // array of post_arr(s), post_arr is array of postObjects 30 | let labels = []; // array of labelObject(s) 31 | 32 | // template generation 33 | function generateTemplates(){ 34 | let flatPosts = posts.reduce((posts_prev,posts_next)=>posts_prev.concat(posts_next)); 35 | let pagination = {next:null,prev:null}; 36 | let fileName = ''; 37 | 38 | // index pages and pagination 39 | posts.forEach( (post_arr,cur_page) => { 40 | // generate pagination 41 | pagination = utils.generatePagination(pagination,posts,cur_page); 42 | // generate fileName 43 | fileName = cur_page === 0 ? `index.html` : `${cur_page+1}.html`; 44 | // generate index template 45 | utils.generateIndexTemplate(post_arr,labels,pagination,fileName); 46 | }); 47 | 48 | // post pages 49 | flatPosts.forEach((post,currentPostIndex) => { 50 | utils.generatePostTemplate(post,labels,flatPosts,currentPostIndex); 51 | }); 52 | 53 | // other pages 54 | utils.generatePageTemplate(); 55 | 56 | // category pages 57 | utils.generateCategoryTemplates(labels,flatPosts) 58 | 59 | // feed template 60 | utils.generateFeedTemplate(flatPosts) 61 | 62 | } 63 | 64 | function startDevMode(){ 65 | 66 | mkdirp.sync(path.join(ROOT_DIR,'dev','category')); 67 | mkdirp.sync(path.join(ROOT_DIR,'dev','posts')); 68 | generateTemplates(); 69 | 70 | const themeWatcher = chokidar.watch([THEME_DIR], { 71 | ignored: /[\/\\]\./ 72 | }); 73 | const draftWatcher = chokidar.watch([DRAFT_DIR], { 74 | ignored: /[\/\\]\./ 75 | }); 76 | 77 | const draftWatcherCallback = () => { 78 | utils.getOfflineFileContents() 79 | .then(offlinePostObjects=>{ 80 | posts[0] = posts[0].slice(offlinePostObjects.length); 81 | posts[0].unshift(...offlinePostObjects); 82 | generateTemplates(); 83 | }); 84 | } 85 | 86 | 87 | themeWatcher 88 | .on('change', (path, stats) => { generateTemplates(); }) 89 | .on('add', (path, stats) => { generateTemplates(); }) 90 | .on('unlink', (path, stats) => { generateTemplates(); }); 91 | 92 | draftWatcher 93 | .on('change', (path, stats) => { draftWatcherCallback(); }) 94 | .on('add', (path, stats) => { draftWatcherCallback(); }) 95 | .on('unlink', (path, stats) => { draftWatcherCallback(); }); 96 | 97 | console.log(chalk.bold.green(`Templates generated. \nAvailable on:\n http://localhost:${PORT}`)); 98 | } 99 | 100 | function getAllPosts(){ 101 | let posts = []; 102 | // this promise returns after there are recursive calls to the IIFE callFetchBlogPosts 103 | // I think this is a bad idea, if you have any other idea, please feel free to suggest 104 | return new Promise((resolve,reject)=>{ 105 | (function callFetchBlogPosts(){ 106 | blog.fetchBlogPosts() 107 | .then(_posts=>{ 108 | if(blog.settings.posts.last_reached){ 109 | resolve(posts); 110 | } 111 | else{ 112 | callFetchBlogPosts(); 113 | } 114 | posts.push(_posts); 115 | }) 116 | .catch(function(err){ 117 | console.log(chalk.bold.red('Could not fetch github data for some reason\nUsing offline data.')); 118 | resolve(posts); 119 | }); 120 | })() 121 | }); 122 | } 123 | 124 | function getAllLabels(){ 125 | return new Promise((resolve,reject)=>{ 126 | blog.fetchAllLabels() 127 | .then(_labels=>{ 128 | resolve(_labels); 129 | }) 130 | .catch(err=>{ 131 | console.log(chalk.bold.red('Could not fetch github label data due to network issue')); 132 | resolve(labels); 133 | }); 134 | }); 135 | } 136 | 137 | 138 | function fetchAndStoreData(){ 139 | Promise.all([getAllPosts(), getAllLabels(),utils.getOfflineFileContents()]) 140 | .then(vals=>{ 141 | spinner.stop(); 142 | posts = vals[0]; 143 | labels = vals[1]; 144 | // adding the offlinePostObjects, i.e vals[2] to the top array element of `posts` 145 | posts[0].unshift(...vals[2]); 146 | startDevMode(); 147 | }) 148 | .catch(err=>{ 149 | spinner.stop(); 150 | utils.getOfflineFileContents() 151 | .then(offlinePostObjects=>{ 152 | posts.push(offlinePostObjects); 153 | startDevMode(); 154 | }) 155 | }) 156 | } 157 | 158 | // start the dev 159 | spinner.start(); 160 | fetchAndStoreData(); 161 | 162 | // start the dev server silently 163 | server.start({ 164 | port: PORT, 165 | directory: path.join(ROOT_DIR,'dev') 166 | }); 167 | -------------------------------------------------------------------------------- /scripts/generate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // the generate scripts skips the drafts and skips watch mode 3 | 4 | process.env.NODE_ENV = 'production'; 5 | 6 | const chokidar = require('chokidar'); 7 | const ora = require('ora'); 8 | const chalk = require('chalk'); 9 | const mkdirp = require('mkdirp'); 10 | 11 | const fs = require('fs'); 12 | const path = require('path'); 13 | 14 | // import configuration files 15 | const init = require('./init'); 16 | const utils = require('./utils.js'); 17 | 18 | // init nunjucks and blog and env variables 19 | const {blog,bc} = init.init(); 20 | const spinner = ora({text:'Fetching posts',spinner:'line'}); 21 | 22 | // initilize some constants 23 | const ROOT_DIR = process.env.ROOT_DIR; 24 | const THEME_DIR = path.join(ROOT_DIR,'themes',bc.meta.blog_theme); 25 | 26 | // global variables, will get rid of them soon 27 | let posts = []; // array of post_arr(s), post_arr is array of postObjects 28 | let labels = []; // array of labelObject(s) 29 | 30 | // template generation 31 | function generateTemplates(){ 32 | let flatPosts = posts.reduce((posts_prev,posts_next)=>posts_prev.concat(posts_next)); 33 | let pagination = {next:null,prev:null}; 34 | let fileName = ''; 35 | 36 | // index pages and pagination 37 | posts.forEach( (post_arr,cur_page) => { 38 | // generate pagination 39 | pagination = utils.generatePagination(pagination,posts,cur_page); 40 | // generate fileName 41 | fileName = cur_page === 0 ? `index.html` : `${cur_page+1}.html`; 42 | // generate index template 43 | utils.generateIndexTemplate(post_arr,labels,pagination,fileName); 44 | }); 45 | 46 | // post pages 47 | flatPosts.forEach((post,currentPostIndex) => { 48 | utils.generatePostTemplate(post,labels,flatPosts,currentPostIndex); 49 | }); 50 | 51 | // other pages 52 | utils.generatePageTemplate(); 53 | 54 | // category pages 55 | utils.generateCategoryTemplates(labels,flatPosts) 56 | 57 | // feed template 58 | utils.generateFeedTemplate(flatPosts) 59 | } 60 | 61 | function startGenerate(){ 62 | mkdirp.sync(path.join(ROOT_DIR,'dist','category')); 63 | mkdirp.sync(path.join(ROOT_DIR,'dist','posts')); 64 | generateTemplates(); 65 | } 66 | 67 | function getAllPosts(){ 68 | let posts = []; 69 | return new Promise((resolve,reject)=>{ 70 | (function callFetchBlogPosts(){ 71 | blog.fetchBlogPosts() 72 | .then(_posts=>{ 73 | if(blog.settings.posts.last_reached){ 74 | resolve(posts); 75 | } 76 | else{ 77 | callFetchBlogPosts(); 78 | } 79 | posts.push(_posts); 80 | }) 81 | .catch(function(err){ 82 | console.log(chalk.bold.red('Could not fetch github data for some reason\nUsing offline data.')); 83 | reject(); 84 | }); 85 | })() 86 | }); 87 | } 88 | 89 | function getAllLabels(){ 90 | return new Promise((resolve,reject)=>{ 91 | blog.fetchAllLabels() 92 | .then(_labels=>{ 93 | resolve(_labels); 94 | }) 95 | .catch(err=>{ 96 | console.log(chalk.bold.red('Could not fetch github label data due to network issue')); 97 | reject(); 98 | }); 99 | }); 100 | } 101 | 102 | 103 | function fetchAndStoreData(){ 104 | Promise.all([getAllPosts(), getAllLabels()]) 105 | .then(vals=>{ 106 | spinner.stop(); 107 | posts = vals[0]; 108 | labels = vals[1]; 109 | startGenerate(); 110 | }) 111 | .catch(err=>{ 112 | spinner.stop(); 113 | console.log(chalk.bold.red('Network issue, try again')); 114 | }) 115 | } 116 | 117 | // start the generation 118 | spinner.start(); 119 | fetchAndStoreData(); 120 | -------------------------------------------------------------------------------- /scripts/help.js: -------------------------------------------------------------------------------- 1 | console.log( 2 | ` 3 | Usage: npm run [SCRIPT NAME] 4 | 5 | Commands: 6 | dev Start a development server in port 3000, output in /dev 7 | generate Generate minified version for the public site, output in /dist 8 | push Pushes contents of /dist to the appropriate branch of repository 9 | draft [FILE NAME] Create a markdown file with minimal boilerplate text inside /drafts 10 | upload Lets you select which drafts to upload to github issues from /drafts 11 | theme [THEME NAME] Create a theme directory with minimal boilerplate files inside /themes 12 | `); 13 | -------------------------------------------------------------------------------- /scripts/init.js: -------------------------------------------------------------------------------- 1 | // init nunjucks, githubblog api and env vars 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const _nunjucks = require('./nunjucks_config.js'); 5 | const gitblog = require('github-blog-api'); 6 | const yaml = require('js-yaml'); 7 | const slug = require('slug'); 8 | 9 | module.exports = { 10 | init: ()=>{ 11 | process.env.ROOT_DIR = path.resolve('.'); 12 | const ROOT_DIR = process.env.ROOT_DIR; 13 | 14 | const bc = yaml.safeLoad(fs.readFileSync(path.join(ROOT_DIR,'_config.yml'), 'utf8')); 15 | const THEME_DIR = path.join(ROOT_DIR,'themes',bc.meta.blog_theme); 16 | let tc = {}; 17 | if(fs.existsSync(path.join(THEME_DIR,'_config.yml'))){ 18 | tc = yaml.safeLoad(fs.readFileSync(path.join(THEME_DIR,'_config.yml'), 'utf8')); 19 | } 20 | 21 | const nunjucks = _nunjucks.init(); 22 | 23 | const blog = gitblog({username:bc.username,repo:bc.repo,author:bc.author}); 24 | blog.setPost({per_page:bc.posts_per_page}); 25 | 26 | 27 | // init slug 28 | slug.defaults.modes['pretty'] = { 29 | replacement: '-', 30 | symbols: true, 31 | remove: /[.]/g, 32 | lower: true, 33 | charmap: slug.charmap, 34 | multicharmap: slug.multicharmap 35 | }; 36 | 37 | return {blog,nunjucks,bc,tc,slug}; 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /scripts/newdraft.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'production'; // required, if not specified will run in watch mode 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const mkdirp = require('mkdirp'); 6 | const chalk = require('chalk'); 7 | const init = require('./init'); 8 | const log = console.log.bind(console,'> '); 9 | init.init(); 10 | 11 | const ROOT_DIR = process.env.ROOT_DIR; 12 | mkdirp.sync(path.join(ROOT_DIR,'drafts')); // create `drafts/` if does not exist 13 | const DRAFT_DIR = path.join(ROOT_DIR,'drafts'); 14 | const fileName = process.argv[2]; 15 | 16 | const markdownTemplate = `--- 17 | title: just a title 18 | labels: 19 | - label sample 20 | --- 21 | 22 | write in markdown... 23 | `; 24 | 25 | if(process.argv.length !== 3){ 26 | log(chalk.bold.red(`can't have filenamewithspaces or a filewithoutaname ;)`)); 27 | }else{ 28 | fs.writeFile(path.join(DRAFT_DIR,fileName), markdownTemplate, 'utf8', (err,res) => { 29 | if (err) throw err; 30 | log(chalk.bold.green(`${fileName} created in ${chalk.yellow(path.join(DRAFT_DIR,fileName))} !`)); 31 | }); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /scripts/newtheme.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'production'; 2 | 3 | if(process.argv.length !== 3){ 4 | throw new RangeError(`You must provide theme name and theme name can't contain spaces`); 5 | } 6 | 7 | const chalk = require('chalk'); 8 | const ncp = require('ncp').ncp; 9 | const mkdirp = require('mkdirp'); 10 | const path = require('path'); 11 | const {bc} = require('./init.js').init(); 12 | 13 | const log = console.log.bind(console,'> '); 14 | 15 | const themeName = process.argv[2]; 16 | const ROOT_DIR = process.env.ROOT_DIR; 17 | const THEME_DIR = path.join(ROOT_DIR,'themes',themeName); 18 | const THEME_DIR_PARENT = path.join(ROOT_DIR,'themes'); 19 | const THEME_SOURCE = path.join(ROOT_DIR,'scripts','themefiles'); 20 | 21 | mkdirp.sync(path.join(THEME_DIR_PARENT,themeName)); 22 | 23 | ncp(THEME_SOURCE, THEME_DIR, function (err) { 24 | if (err) { 25 | return console.error(err); 26 | } 27 | console.log('done!'); 28 | }); 29 | -------------------------------------------------------------------------------- /scripts/nunjucks_config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const _nunjucks = require('nunjucks'); 6 | const yaml = require('js-yaml'); 7 | 8 | 9 | module.exports = { 10 | init: ()=>{ 11 | const ROOT_DIR = process.env.ROOT_DIR; 12 | const bc = yaml.safeLoad(fs.readFileSync(path.join(ROOT_DIR,'_config.yml'), 'utf8')); 13 | let nunjucks_opts = { autoescape: true, trimBlocks: true, lstripBlocks: true }; 14 | 15 | if( process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test" ){ 16 | nunjucks_opts = Object.assign(nunjucks_opts,{watch: false}); 17 | } 18 | else{ 19 | nunjucks_opts = Object.assign(nunjucks_opts,{watch: true}); 20 | } 21 | 22 | const nunjucks = _nunjucks.configure(path.join(ROOT_DIR,'themes',bc.meta.blog_theme), nunjucks_opts); 23 | 24 | // filters 25 | nunjucks.addFilter('date', function(str, count) { 26 | // date filter 27 | let dateObj = new Date(str); 28 | return `${dateObj.getDate()}/${+dateObj.getMonth()+1}/${dateObj.getFullYear()}`; 29 | }); 30 | 31 | nunjucks.addFilter('stringify', function(obj, count) { 32 | // stringify filter 33 | return JSON.stringify(obj); 34 | }); 35 | 36 | nunjucks.addFilter('addbaseurl', function(str, count) { 37 | // baseurl filter 38 | if( process.env.NODE_ENV === "development"){ 39 | return str; 40 | } 41 | else{ 42 | if(!bc.meta.userpage){ 43 | return `/${bc.meta.baseurl}${str}`; 44 | } 45 | else{ 46 | return str; 47 | } 48 | } 49 | }); 50 | 51 | return nunjucks; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /scripts/offline.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | process.env.NODE_ENV = 'production'; 3 | 4 | const path = require('path'); 5 | const ora = require('ora'); 6 | const inquirer = require('inquirer'); 7 | const chalk = require('chalk'); 8 | const rimraf = require('rimraf'); 9 | const fs = require('fs'); 10 | const gitblog = require('github-blog-api'); 11 | const utils = require('./utils.js'); 12 | const init = require('./init.js'); 13 | 14 | const {blog,bc} = init.init(); 15 | 16 | // initilize some constants 17 | const ROOT_DIR = process.env.ROOT_DIR; 18 | require('dotenv').config({path:path.join(ROOT_DIR,'.env')}); 19 | const GITHUB_AUTH_TOKEN = process.env.GITHUB_AUTH_TOKEN; 20 | 21 | const uploadSpinner = ora({text:'Uploading posts',spinner:'line'}); 22 | const draftPrompt = inquirer.createPromptModule(); 23 | const log = console.log.bind(console,'> '); 24 | let uploadedFileNames = []; 25 | 26 | // non-exported functions 27 | const getUploadPromises = () => { 28 | return new Promise((resolve,reject)=>{ 29 | utils.getOfflineFileContents() 30 | .then( offlinePostObjects => { 31 | 32 | let offlinePostNames = offlinePostObjects.map(post=>({name:post.title})) 33 | 34 | if(offlinePostNames.length<1){ 35 | reject(new TypeError("No posts in drafts directory")); 36 | } else { 37 | draftPrompt([ 38 | { 39 | type: 'checkbox', 40 | message: 'Select posts to upload', 41 | name: 'posts', 42 | choices: offlinePostNames, 43 | validate: answer => { 44 | if (answer.length < 1) { 45 | return 'You did not select any post, no post will be uploaded. hit ctrl+c'; 46 | reject(); 47 | } 48 | return true; 49 | } 50 | } 51 | ]).then(answers => { 52 | // upload only selected posts 53 | offlinePostObjects = offlinePostObjects.filter(post => answers.posts.indexOf(post.title)>-1 ); 54 | // update uploadedFileNames with fileNames of posts to be uploaded 55 | uploadedFileNames = offlinePostObjects.map(post=>post.fileName); 56 | // return the promise 57 | uploadSpinner.start(); 58 | resolve(offlinePostObjects.map(postObject=>blog.createPost(postObject,GITHUB_AUTH_TOKEN))); 59 | }); 60 | } 61 | }); 62 | }) 63 | } 64 | 65 | // exported functions 66 | const uploadPosts = () => { 67 | getUploadPromises() 68 | .then(uploadPromises => { 69 | Promise.all(uploadPromises) 70 | .then(res => { 71 | uploadSpinner.stop(); 72 | 73 | log(chalk.bold.green('Posts uploaded!')); 74 | log(chalk.bold.yellow(`run ${chalk.bold.blue('npm run generate')} or ${chalk.bold.blue('npm run dev')} to see the uploaded posts in the static site`)); 75 | 76 | // delete the uploaded files 77 | uploadedFileNames.forEach( fileName => { 78 | let deleteFileName = path.join(ROOT_DIR,'drafts',fileName); 79 | rimraf.sync(deleteFileName); 80 | }); 81 | 82 | log(chalk.bold.red(`the uploaded post is deleted from drafts`)); 83 | }) 84 | .catch(err=>{ 85 | uploadSpinner.stop(); 86 | log(chalk.bold.red('Could not upload')); 87 | console.log(err); 88 | }); 89 | }) 90 | .catch( err => { 91 | log(chalk.bold.red(err.message)); 92 | }) 93 | } 94 | 95 | module.exports = { 96 | uploadPosts 97 | } 98 | -------------------------------------------------------------------------------- /scripts/push.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'production'; 2 | 3 | const init = require('./init.js'); 4 | const chalk = require('chalk'); 5 | const {bc} = init.init(); 6 | const log = console.log.bind(console,'> '); 7 | 8 | //const exec = require('child_process').exec; 9 | const exec = require('child_process').execSync; 10 | 11 | const callback = (err) => { 12 | if (err){ 13 | throw err;console.log('check repo url') 14 | } 15 | log(chalk.bold.green('pushed changes')); 16 | } 17 | 18 | if(bc.meta.userpage){ 19 | 20 | log(chalk.bold.green(`Pushing changes to master branch of ${bc.username}/${bc.username}.github.io`)); 21 | 22 | let subtreecommand = `git subtree split --prefix dist`; 23 | // same commit message for every commit 24 | let commitmessage = `blog updates`; 25 | 26 | try { 27 | exec(`git add -A`); 28 | exec(`git commit -m '${commitmessage}'`); 29 | } 30 | finally { 31 | exec(`git push https://github.com/${bc.username}/${bc.username}.github.io.git \`${subtreecommand}\`:master --force`, callback); 32 | } 33 | 34 | 35 | } else { 36 | 37 | // else clause: this is a repopage blog 38 | log(chalk.bold.green(`Pushing changes to gh-pages branch of ${bc.username}/${bc.repo}`)); 39 | 40 | let subtreecommand = `git subtree push --prefix dist`; 41 | let commitmessage = `blog updates`; 42 | 43 | try { 44 | exec(`git add -A`); 45 | exec(`git commit -m '${commitmessage}'`); 46 | } 47 | finally { 48 | exec(`${subtreecommand} origin gh-pages`, callback); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /scripts/themefiles/_config.yml: -------------------------------------------------------------------------------- 1 | # Theme Settings [THESE ARE JUST SAMPLE FIELDS] 2 | # All these fields are available under the `tc`(theme config) object for all templates and client side javascript too 3 | 4 | title: "Theme Name" 5 | description: "Theme Description that can be long" 6 | google_verify: epFgX0s_0RM3CdjwFcsg8s9ZBOLyaIUH-o # Put your Google Verification here 7 | google_analytics: UA-XXXXXXX-X # Put your Google Analytics code 8 | 9 | # Author Info 10 | author_name: "YOUR_NAME" # Your name here 11 | author_email: datboi@gmail.com # Your email here 12 | author_gravatar: 2b38b1b0e7e08b69379bd61582adf0c8 # Your Gravatar md5 hash here for logo 13 | twitter_username: geekodour # Your Twitter username here 14 | github_username: geekodour # Your GitHub username here 15 | 16 | # Site Settings 17 | baseurl: "" # Base URL must end WITHOUT a slash, default: "" 18 | permalink: /notes/:title # Post permalink 19 | timezone: Asia/Kuala_Lumpur 20 | -------------------------------------------------------------------------------- /scripts/themefiles/category_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ label.name }} - {{ bc.meta._blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'category'; 7 | window.blogInfo.label = '{{label.name}}'; 8 | {% endblock %} 9 | 10 | {% block pagecontent %} 11 |

Posts tagged "{{ label.name }}"

12 | {% if bc.others.template_cat_posts %} 13 | {% for post in posts %} 14 |
15 | {{ post.title }} 16 |
17 | {% endfor %} 18 | {% endif %} 19 | 20 | 21 | {% if not bc.others.template_cat_posts %} 22 |
23 |
Load more
24 |
25 | {% endif %} 26 | 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /scripts/themefiles/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ bc.meta.blog_name }} 5 | {{ bc.meta.blog_description }} 6 | {{ ""|addbaseurl }} 7 | {% for post in posts %} 8 | 9 | {{ post.title }} 10 | {{ post.content }} 11 | {{ post.date }} 12 | {{ "/posts/"|addbaseurl }}{{ post.slug }} 13 | 14 | {% endfor %} 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/themefiles/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ bc.meta.blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'index'; 7 | {% endblock %} 8 | 9 | {% block pagecontent %} 10 | 11 |
    12 | {% for post in posts %} 13 |
  • 14 | 17 |
    18 | {{ post.title }} 19 |
    20 |
  • 21 | {% endfor %} 22 |
23 | 24 | {% include 'snippets/pagination.html' %} 25 | 26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /scripts/themefiles/pages/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
11 |

not found page

12 | 404 page not found 13 |
14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /scripts/themefiles/pages/about.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
11 |

About Page

12 | I am about page 13 |
14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /scripts/themefiles/pages/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
11 |

I am some text

12 | This little place in the internet is about me 13 | If this page exists inside `/pages` then it will be the homepage. 14 | Otherwise, the `index.html` in the root directory of the theme will be the homepage. 15 | that is, the blog page will be the homepage. 16 |
17 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /scripts/themefiles/pages/standalone.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | title 12 | 13 | 14 | 15 | 16 | 17 | 18 | I AM SOME TEXT 19 | 20 | 21 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /scripts/themefiles/pages/work.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
11 |

My work

12 |

OpenSource Contributions

13 |

Personal Projects

14 |

Client Work

15 |
16 | 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /scripts/themefiles/post_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ post.title }} - {{ bc.meta._blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'post'; 7 | window.blogInfo.postId = '{{ post.id }}'; 8 | {% endblock %} 9 | 10 | {% block pagecontent %} 11 |
12 | 13 | 20 | 21 |
22 | {{ post.html|safe }} 23 |
24 | 25 |
26 | 27 | {% include 'snippets/post_bottom_navigation.html' %} 28 | {% include 'snippets/comment.html' %} 29 | 30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /scripts/themefiles/snippets/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}{{ bc.meta.blog_name }}{% endblock title %} 8 | 9 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | 31 | {% include 'snippets/navbar.html' %} 32 | 33 | {% block pagecontent %}{% endblock %} 34 | 35 | {% include 'snippets/footer.html' %} 36 | 37 | 38 | {% block javascript %} 39 | {% if bc.comment.isGithubAuth %} {% endif %} 40 | {% if bc.comment.isDisqus %} {% endif %} 41 | 42 | 43 | 44 | {% endblock javascript %} 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /scripts/themefiles/snippets/comment.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | {% if bc.comment.isGithubAuth and bc.comment.isGithub and not bc.comment.disabled %} 7 |
8 |
9 | let me know what you think about this post in the comments.😅 10 |
11 |

Leave a Comment

12 |
13 |
14 |
15 | 16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 | 24 | {% elif bc.comment.isGithub and not bc.comment.disabled %} 25 | 28 | 29 | {% endif %} 30 | 31 | 32 |
33 | 34 | 35 | 36 | {% if not bc.comment.disabled and not bc.comment.isDisqus %} 37 |
38 |
Load more
39 |
40 | {% endif %} 41 | 42 |
43 | -------------------------------------------------------------------------------- /scripts/themefiles/snippets/footer.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /scripts/themefiles/snippets/navbar.html: -------------------------------------------------------------------------------- 1 | 4 |
5 | 13 |
14 | -------------------------------------------------------------------------------- /scripts/themefiles/snippets/pagination.html: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | -------------------------------------------------------------------------------- /scripts/themefiles/snippets/post_bottom_navigation.html: -------------------------------------------------------------------------------- 1 | 2 | 19 | -------------------------------------------------------------------------------- /scripts/themefiles/static/css/main.scss: -------------------------------------------------------------------------------- 1 | @import 'prism.css'; 2 | -------------------------------------------------------------------------------- /scripts/themefiles/static/css/prism.css: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript&plugins=line-numbers+toolbar+show-language+copy-to-clipboard */ 2 | /** 3 | * okaidia theme for JavaScript, CSS and HTML 4 | * Loosely based on Monokai textmate theme by http://www.monokai.nl/ 5 | * @author ocodia 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: #f8f8f2; 11 | background: none; 12 | text-shadow: 0 1px rgba(0, 0, 0, 0.3); 13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | /* Code blocks */ 32 | pre[class*="language-"] { 33 | padding: 1em; 34 | margin: .5em 0; 35 | overflow: auto; 36 | border-radius: 0.3em; 37 | } 38 | 39 | :not(pre) > code[class*="language-"], 40 | pre[class*="language-"] { 41 | background: #272822; 42 | } 43 | 44 | /* Inline code */ 45 | :not(pre) > code[class*="language-"] { 46 | padding: .1em; 47 | border-radius: .3em; 48 | white-space: normal; 49 | } 50 | 51 | .token.comment, 52 | .token.prolog, 53 | .token.doctype, 54 | .token.cdata { 55 | color: slategray; 56 | } 57 | 58 | .token.punctuation { 59 | color: #f8f8f2; 60 | } 61 | 62 | .namespace { 63 | opacity: .7; 64 | } 65 | 66 | .token.property, 67 | .token.tag, 68 | .token.constant, 69 | .token.symbol, 70 | .token.deleted { 71 | color: #f92672; 72 | } 73 | 74 | .token.boolean, 75 | .token.number { 76 | color: #ae81ff; 77 | } 78 | 79 | .token.selector, 80 | .token.attr-name, 81 | .token.string, 82 | .token.char, 83 | .token.builtin, 84 | .token.inserted { 85 | color: #a6e22e; 86 | } 87 | 88 | .token.operator, 89 | .token.entity, 90 | .token.url, 91 | .language-css .token.string, 92 | .style .token.string, 93 | .token.variable { 94 | color: #f8f8f2; 95 | } 96 | 97 | .token.atrule, 98 | .token.attr-value, 99 | .token.function { 100 | color: #e6db74; 101 | } 102 | 103 | .token.keyword { 104 | color: #66d9ef; 105 | } 106 | 107 | .token.regex, 108 | .token.important { 109 | color: #fd971f; 110 | } 111 | 112 | .token.important, 113 | .token.bold { 114 | font-weight: bold; 115 | } 116 | .token.italic { 117 | font-style: italic; 118 | } 119 | 120 | .token.entity { 121 | cursor: help; 122 | } 123 | 124 | pre.line-numbers { 125 | position: relative; 126 | padding-left: 3.8em; 127 | counter-reset: linenumber; 128 | } 129 | 130 | pre.line-numbers > code { 131 | position: relative; 132 | } 133 | 134 | .line-numbers .line-numbers-rows { 135 | position: absolute; 136 | pointer-events: none; 137 | top: 0; 138 | font-size: 100%; 139 | left: -3.8em; 140 | width: 3em; /* works for line-numbers below 1000 lines */ 141 | letter-spacing: -1px; 142 | border-right: 1px solid #999; 143 | 144 | -webkit-user-select: none; 145 | -moz-user-select: none; 146 | -ms-user-select: none; 147 | user-select: none; 148 | 149 | } 150 | 151 | .line-numbers-rows > span { 152 | pointer-events: none; 153 | display: block; 154 | counter-increment: linenumber; 155 | } 156 | 157 | .line-numbers-rows > span:before { 158 | content: counter(linenumber); 159 | color: #999; 160 | display: block; 161 | padding-right: 0.8em; 162 | text-align: right; 163 | } 164 | pre.code-toolbar { 165 | position: relative; 166 | } 167 | 168 | pre.code-toolbar > .toolbar { 169 | position: absolute; 170 | top: .3em; 171 | right: .2em; 172 | transition: opacity 0.3s ease-in-out; 173 | opacity: 0; 174 | } 175 | 176 | pre.code-toolbar:hover > .toolbar { 177 | opacity: 1; 178 | } 179 | 180 | pre.code-toolbar > .toolbar .toolbar-item { 181 | display: inline-block; 182 | } 183 | 184 | pre.code-toolbar > .toolbar a { 185 | cursor: pointer; 186 | } 187 | 188 | pre.code-toolbar > .toolbar button { 189 | background: none; 190 | border: 0; 191 | color: inherit; 192 | font: inherit; 193 | line-height: normal; 194 | overflow: visible; 195 | padding: 0; 196 | -webkit-user-select: none; /* for button */ 197 | -moz-user-select: none; 198 | -ms-user-select: none; 199 | } 200 | 201 | pre.code-toolbar > .toolbar a, 202 | pre.code-toolbar > .toolbar button, 203 | pre.code-toolbar > .toolbar span { 204 | color: #bbb; 205 | font-size: .8em; 206 | padding: 0 .5em; 207 | background: #f5f2f0; 208 | background: rgba(224, 224, 224, 0.2); 209 | box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); 210 | border-radius: .5em; 211 | } 212 | 213 | pre.code-toolbar > .toolbar a:hover, 214 | pre.code-toolbar > .toolbar a:focus, 215 | pre.code-toolbar > .toolbar button:hover, 216 | pre.code-toolbar > .toolbar button:focus, 217 | pre.code-toolbar > .toolbar span:hover, 218 | pre.code-toolbar > .toolbar span:focus { 219 | color: inherit; 220 | text-decoration: none; 221 | } 222 | 223 | -------------------------------------------------------------------------------- /scripts/themefiles/static/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/scripts/themefiles/static/images/favicon.png -------------------------------------------------------------------------------- /scripts/themefiles/static/images/gravatar_wrapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/scripts/themefiles/static/images/gravatar_wrapper.png -------------------------------------------------------------------------------- /scripts/themefiles/static/images/touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/scripts/themefiles/static/images/touch-icon.png -------------------------------------------------------------------------------- /scripts/themefiles/static/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript for gitpushblog, webpack + init stuff 3 | */ 4 | 5 | import { initCommentSystem, initPostCategoryPage, displaySignOut } from './utils'; 6 | import { firebaseService } from './services'; 7 | 8 | // only imported assets will be available inside assets directory 9 | 10 | import '../css/main.scss'; 11 | import '../images/favicon.png'; 12 | 13 | // end of file imports 14 | 15 | const blogInfo = window.blogInfo; 16 | const bc = blogInfo.bc; 17 | 18 | // init firebase and display signout if signedin 19 | if(bc.comment.isGithubAuth){ 20 | firebaseService.init(); 21 | displaySignOut(); 22 | } 23 | 24 | switch(blogInfo.pageType){ 25 | case "index": 26 | break; 27 | case "post": 28 | initCommentSystem(); 29 | break; 30 | case "category": 31 | // you can enable async loading of category posts by toggling template_cat_posts 32 | // by default this is false 33 | if(!bc.others.template_cat_posts){ 34 | initPostCategoryPage(); 35 | } 36 | break; 37 | default: 38 | break; 39 | } 40 | 41 | 42 | /* 43 | * Add your custom javascript below 44 | */ 45 | 46 | console.log('wow!'); 47 | -------------------------------------------------------------------------------- /scripts/themefiles/static/js/services.js: -------------------------------------------------------------------------------- 1 | const bc = window.blogInfo.bc; 2 | 3 | const firebaseInit = ()=>{ 4 | let config = bc.firebaseConfig; 5 | firebase.initializeApp(config); 6 | } 7 | 8 | const githubSignIn = ()=>{ 9 | let provider = new firebase.auth.GithubAuthProvider(); 10 | // this `scope` takes private repo permissions 11 | // need a lower permission than access to private repo. 12 | // any `scope` that only enables to comment on issues? 13 | provider.addScope('repo'); 14 | return new Promise((resolve,reject)=>{ 15 | firebase.auth().signInWithPopup(provider) 16 | .then(function(result) { 17 | let token = result.credential.accessToken; 18 | resolve(token); 19 | }) 20 | .catch(function(error) { 21 | // handle this, right now it's just copy paste from docs 22 | let errorCode = error.code; 23 | }); 24 | }); 25 | } 26 | 27 | const disqusInit = ()=>{ 28 | let disqus_config = function () { 29 | this.page.url = location.href; 30 | this.page.identifier = location.href; 31 | }; 32 | (function() { 33 | var d = document, s = d.createElement('script'); 34 | s.src = `https://${bc.comment.disqus_id}.disqus.com/embed.js`; 35 | s.setAttribute('data-timestamp', +new Date()); 36 | (d.head || d.body).appendChild(s); 37 | })(); 38 | } 39 | 40 | export const firebaseService = { 41 | init: firebaseInit, 42 | signIn: githubSignIn 43 | } 44 | 45 | export const disqusService = { 46 | init: disqusInit 47 | } 48 | -------------------------------------------------------------------------------- /scripts/themefiles/static/js/utils.js: -------------------------------------------------------------------------------- 1 | import gitBlog from 'github-blog-api'; 2 | import { disqusService, firebaseService } from './services'; 3 | 4 | const blogInfo = window.blogInfo; 5 | const bc = blogInfo.bc; 6 | 7 | const myblog = gitBlog({username:bc.username,repo:bc.repo,author:bc.author}); 8 | myblog.setPost({per_page:bc.posts_per_page}); 9 | myblog.setComment({per_page:bc.comments_per_page}); 10 | 11 | const domNodes = {}; 12 | const message = { 13 | signedIn : `You are signed in`, 14 | signOutErr : `Could not signout`, 15 | addedComment: `Your comment is added`, 16 | emptyComment: `Your comment is empty, please write something`, 17 | allCommentsLoaded: `All comments loaded`, 18 | allPostsLoaded: `All posts loaded` 19 | }; 20 | 21 | // get all the required DOM elements for posts and comments 22 | if(bc.comment.isGithubAuth) 23 | { 24 | domNodes.signInButton = document.getElementById("signin_button"); 25 | domNodes.signOutButton = document.getElementById("signout_button"); 26 | } 27 | 28 | if( (!bc.others.template_cat_posts && blogInfo.pageType === 'category') || (blogInfo.pageType === 'post')) 29 | { 30 | domNodes.loadMoreButtonContainer = document.getElementById('loadmore_button_container'); 31 | domNodes.loadMoreButton = document.getElementById('loadmore_button'); 32 | } 33 | 34 | if(blogInfo.pageType === 'post') 35 | { 36 | domNodes.commentsContainer = document.getElementById('comments_container'); 37 | domNodes.commentTextarea = document.querySelector('#comments textarea'); 38 | domNodes.commentInfoBox = document.getElementById('comment-info-box'); 39 | } 40 | 41 | if(blogInfo.pageType === 'category') 42 | { 43 | domNodes.postsListContainer = document.getElementById('category_posts_container'); 44 | } 45 | 46 | 47 | 48 | const handleSignInAndComment = (event) => { 49 | event.preventDefault(); 50 | if(domNodes.commentTextarea.value){ 51 | firebaseService.signIn() 52 | .then(token=>{ 53 | 54 | domNodes.commentInfoBox.innerText = message.signedIn; 55 | displaySignOut(); 56 | 57 | myblog.createComment({body:domNodes.commentTextarea.value},blogInfo.postId,token) 58 | .then(comment=>{ 59 | // update notification 60 | domNodes.commentInfoBox.innerText = message.addedComment; 61 | // update comment thread 62 | domNodes.commentsContainer.insertAdjacentHTML('beforeend', getCommentHTML(comment)); 63 | }); 64 | }); 65 | } 66 | else{ 67 | // if comment is empty, inform user 68 | domNodes.commentInfoBox.innerText = message.emptyComment; 69 | } 70 | } 71 | 72 | const handleSignOut = () => { 73 | firebase.auth().signOut() 74 | .then(function() { 75 | // reload on signout 76 | window.location.reload(); 77 | }) 78 | .catch(function(error) { 79 | domNodes.commentInfoBox.innerText = message.signOutErr; 80 | }); 81 | } 82 | 83 | 84 | const getCommentHTML = comment => { 85 | // return html needed for comments 86 | // please modify these according to the css library you use 87 | // here using css classes from KeepItSimple20 Theme. 88 | // for disqus, no style is required 89 | if(bc.comment.isGithub){ 90 | return ` 91 |
92 |
93 | 94 |
95 |
96 | ${comment.user.username} 97 |
98 | 99 |
100 |
101 |
102 |
103 | ${comment.html} 104 |
105 |
106 |
107 | `; 108 | } 109 | else{ 110 | return `
`; 111 | } 112 | } 113 | 114 | 115 | const getPostListItemHTML = post => { 116 | return `
  • ${post.title}
  • ` 117 | } 118 | 119 | const updateGithubComments = ()=>{ 120 | // add `is-loading` class 121 | domNodes.loadMoreButton.classList.add('is-loading'); 122 | // fetch 123 | myblog.fetchBlogPostComments(blogInfo.postId).then(comments=>{ 124 | // remove `is-loading` class 125 | domNodes.loadMoreButton.classList.remove('is-loading'); 126 | // append comments 127 | comments.forEach(comment=>{ 128 | domNodes.commentsContainer.insertAdjacentHTML('beforeend', getCommentHTML(comment)); 129 | }); 130 | // update loadmore button container if all comments are loaded 131 | if(myblog.settings.comments.done_posts.indexOf(blogInfo.postId) > -1){ 132 | domNodes.loadMoreButtonContainer.innerHTML = message.allCommentsLoaded; 133 | } 134 | }); 135 | } 136 | 137 | 138 | const updateCategoryList = () => { 139 | // add `is-loading` class 140 | domNodes.loadMoreButton.classList.add('is-loading'); 141 | // fetch 142 | myblog.fetchBlogPosts([blogInfo.label]).then(posts=>{ 143 | // remove `is-loading` class 144 | domNodes.loadMoreButton.classList.remove('is-loading'); 145 | // append posts 146 | posts.forEach(post=>{ 147 | domNodes.postsListContainer.insertAdjacentHTML('beforeend', getPostListItemHTML(post)); 148 | }); 149 | // update loadmore button container if all posts are loaded 150 | if(myblog.settings.posts.last_reached){ 151 | domNodes.loadMoreButtonContainer.innerHTML = message.allPostsLoaded; 152 | } 153 | }); 154 | } 155 | 156 | export const initPostCategoryPage = () => { 157 | updateCategoryList(); 158 | domNodes.loadMoreButton.addEventListener("click", updateCategoryList); 159 | } 160 | 161 | 162 | export const initCommentSystem = () => { 163 | if(!bc.comment.disabled){ 164 | if(bc.comment.isGithub){ 165 | // setup github comments 166 | updateGithubComments(); 167 | domNodes.loadMoreButton.addEventListener("click", updateGithubComments); 168 | if(bc.comment.isGithubAuth){ 169 | // setup github auth and auth comments 170 | domNodes.signInButton.addEventListener("click", handleSignInAndComment); 171 | domNodes.signOutButton.addEventListener("click", handleSignOut); 172 | } 173 | } 174 | else if(bc.comment.isDisqus){ 175 | // setup disqus 176 | domNodes.commentsContainer.innerHTML += getCommentHTML(); 177 | disqusService.init(); 178 | } 179 | } 180 | } 181 | 182 | export const displaySignOut = () => { 183 | if(firebase.auth().currentUser){ 184 | domNodes.signOutButton.style.display = 'block'; 185 | } else { 186 | domNodes.signOutButton.style.display = 'none'; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /scripts/upload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | process.env.NODE_ENV = 'production'; 3 | const offline = require('./offline.js'); 4 | 5 | offline.uploadPosts(); 6 | -------------------------------------------------------------------------------- /scripts/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mkdirp = require('mkdirp'); 4 | const marked = require('marked'); 5 | const fs = require('fs'); 6 | const map = require('async/map'); 7 | //const slugify = require('slugify'); 8 | const path = require('path'); 9 | const yamlFront = require('yaml-front-matter'); 10 | const _nunjucks = require('./nunjucks_config.js'); 11 | const init = require('./init'); 12 | 13 | // init nunjucks and blog and env variables 14 | // tc: theme_config, bc: blog_config 15 | const {nunjucks,bc,tc,slug} = init.init(); 16 | 17 | // inits 18 | const ROOT_DIR = process.env.ROOT_DIR; 19 | const THEME_DIR = path.join(ROOT_DIR,'themes',bc.meta.blog_theme); 20 | const DIR_NAME = process.env.NODE_ENV === 'production'?'dist':'dev'; // output directory 21 | 22 | const contextObject = { 23 | bc: bc, 24 | tc: tc, 25 | baseurl: process.env.NODE_ENV === 'development'?'':bc.meta.baseurl 26 | } 27 | 28 | // non-exported functions 29 | const createPostObject = (fileName,cb) =>{ 30 | let content = fs.readFileSync(path.join(ROOT_DIR,'drafts',fileName),{encoding:"utf8"}); 31 | const post = yamlFront.loadFront(content); 32 | post.slug = slug(post.title); 33 | post.html = marked(post.__content); 34 | post.body = post.__content; 35 | post.fileName = fileName; 36 | post.labels = post.labels.map(label=>({name:label})); 37 | cb(null,post); 38 | } 39 | 40 | // exported functions 41 | const generatePostTemplate = (post,labels,posts,currentPostIndex)=>{ 42 | let fileName = `${post.slug}.html`; 43 | let renderContent = nunjucks.render('post_page.html', 44 | Object.assign(contextObject,{ 45 | post: post, 46 | labels: labels, 47 | posts: posts, 48 | postIndex: currentPostIndex 49 | }) 50 | ); 51 | 52 | fs.writeFile(path.join(ROOT_DIR,DIR_NAME,'posts',fileName), renderContent, (err) => { 53 | if(err) { console.log("disk error"); } 54 | }); 55 | } 56 | 57 | const generateIndexTemplate = (posts,labels,pagination,fileName) => { 58 | 59 | 60 | let blogWritePath = path.join(ROOT_DIR,DIR_NAME,fileName) 61 | const indexContextObject = { 62 | posts: posts, 63 | labels: labels, 64 | pagination:pagination 65 | }; 66 | 67 | if(fs.existsSync(path.join(THEME_DIR,'pages','index.html'))){ 68 | mkdirp.sync(path.join(ROOT_DIR,DIR_NAME,'blog')); 69 | blogWritePath = path.join(ROOT_DIR,DIR_NAME,'blog',fileName); 70 | indexContextObject.hasHomepage = true; 71 | } 72 | 73 | // index template generation 74 | const renderContent = nunjucks.render('index.html', 75 | Object.assign(contextObject, indexContextObject) 76 | ); 77 | 78 | fs.writeFile(blogWritePath, renderContent, (err) => { 79 | if(err) { return console.log(err); } 80 | }); 81 | } 82 | 83 | const generateCategoryTemplates = (labels,posts) => { 84 | labels.forEach((label)=>{ 85 | let postsWithLabel = posts.filter(post => post.labels.map(label=>label.name).indexOf(label.name)>-1 ); 86 | const renderContent = nunjucks.render('category_page.html', 87 | Object.assign(contextObject,{ 88 | labels: labels, 89 | label:label, 90 | posts: postsWithLabel 91 | }) 92 | ); 93 | fs.writeFile(path.join(ROOT_DIR,DIR_NAME,'category',`${label.slug}.html`),renderContent, (err) => { 94 | if(err) { return console.log(err); } 95 | }); 96 | }); 97 | } 98 | 99 | const generatePageTemplate = () => { 100 | const pageTemplatesFiles = fs.readdirSync(path.join(THEME_DIR,'pages')); 101 | pageTemplatesFiles.forEach(function(fileName){ 102 | let renderContent = nunjucks.render(path.join('pages',fileName), 103 | Object.assign(contextObject,{}) 104 | ); 105 | fs.writeFileSync(path.join(ROOT_DIR,DIR_NAME,fileName),renderContent); 106 | }); 107 | } 108 | 109 | const generateFeedTemplate = (posts) => { 110 | if(fs.existsSync(path.join(THEME_DIR,'feed.xml'))){ 111 | const renderContent = nunjucks.render('feed.xml', 112 | Object.assign(contextObject,{ posts : posts }) 113 | ); 114 | 115 | fs.writeFileSync(path.join(ROOT_DIR,DIR_NAME,'feed.xml'),renderContent); 116 | } 117 | } 118 | 119 | const getOfflineFileContents = () => { 120 | return new Promise((resolve,reject)=>{ 121 | let fileNames = fs.readdirSync(path.join(ROOT_DIR,'drafts')); 122 | fileNames = fileNames.filter(fileName => !/~$/.test(fileName)) // needed to skip backup~ files 123 | // using async map here, any idea how we'll do it without async map? 124 | map(fileNames, createPostObject, function(err, posts) { 125 | resolve(posts); 126 | }); 127 | }); 128 | } 129 | 130 | const generatePagination = (pagination,posts,cur_page) => { 131 | // no. of `post_arrs` === no. of pages 132 | // i.e `posts.length` === no. of pages 133 | // `cur_page` is the index from forEach 134 | 135 | // the pagination is sort of a hack right now 136 | // when using with nunjucks. need a better solution 137 | 138 | return Object.assign(pagination, 139 | { 140 | next: (posts.length === cur_page+1) ? 0 : cur_page+2, 141 | prev: cur_page > 0 142 | ? cur_page == 1 ? 'index' : cur_page 143 | : 0 144 | } 145 | ); 146 | } 147 | 148 | module.exports = { 149 | generatePostTemplate, 150 | generateIndexTemplate, 151 | generateCategoryTemplates, 152 | generatePageTemplate, 153 | generateFeedTemplate, 154 | getOfflineFileContents, 155 | generatePagination 156 | }; 157 | -------------------------------------------------------------------------------- /themes/default-plain/_config.yml: -------------------------------------------------------------------------------- 1 | # Theme Settings [THESE ARE JUST SAMPLE FIELDS] 2 | # All these fields are available under the `tc`(theme config) object for all templates and client side javascript too 3 | 4 | title: "Theme Name" 5 | description: "Theme Description that can be long" 6 | google_verify: epFgX0s_0RM3CdjwFcsg8s9ZBOLyaIUH-o # Put your Google Verification here 7 | google_analytics: UA-XXXXXXX-X # Put your Google Analytics code 8 | 9 | # Author Info 10 | author_name: "YOUR_NAME" # Your name here 11 | author_email: datboi@gmail.com # Your email here 12 | author_gravatar: 2b38b1b0e7e08b69379bd61582adf0c8 # Your Gravatar md5 hash here for logo 13 | twitter_username: geekodour # Your Twitter username here 14 | github_username: geekodour # Your GitHub username here 15 | 16 | # Site Settings 17 | baseurl: "" # Base URL must end WITHOUT a slash, default: "" 18 | permalink: /notes/:title # Post permalink 19 | timezone: Asia/Kuala_Lumpur 20 | -------------------------------------------------------------------------------- /themes/default-plain/category_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ label.name }} - {{ bc.meta._blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'category'; 7 | window.blogInfo.label = '{{label.name}}'; 8 | {% endblock %} 9 | 10 | {% block pagecontent %} 11 |
    12 |
    13 |

    Posts tagged "{{ label.name }}"

    14 |
    15 | {% if bc.others.template_cat_posts %} 16 | {% for post in posts %} 17 |
    18 | {{ post.title }} 19 |
    20 | {% endfor %} 21 | {% endif %} 22 | 23 | 24 | {% if not bc.others.template_cat_posts %} 25 |
    26 |
    Load more
    27 |
    28 | {% endif %} 29 |
    30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /themes/default-plain/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ bc.meta.blog_name }} 5 | {{ bc.meta.blog_description }} 6 | {{ ""|addbaseurl }} 7 | {% for post in posts %} 8 | 9 | {{ post.title }} 10 | {{ post.content }} 11 | {{ post.date }} 12 | {{ "/posts/"|addbaseurl }}{{ post.slug }} 13 | 14 | {% endfor %} 15 | 16 | 17 | -------------------------------------------------------------------------------- /themes/default-plain/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ bc.meta.blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'index'; 7 | {% endblock %} 8 | 9 | {% block pagecontent %} 10 |
    11 |
      12 | {% for post in posts %} 13 |
    • 14 | 17 |
      18 | {{ post.title }} 19 |
      20 |
    • 21 | {% endfor %} 22 |
    23 | 24 | {% include 'snippets/pagination.html' %} 25 |
    26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /themes/default-plain/pages/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
    11 |

    not found page

    12 | 404 page not found 13 |
    14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /themes/default-plain/pages/about.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
    11 |

    About Page

    12 | I am about page 13 |
    14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /themes/default-plain/pages/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
    11 |

    I am some text

    12 | This little place in the internet is about me 13 |
    14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /themes/default-plain/pages/standalone.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | title 12 | 13 | 14 | 15 | 16 | 17 | 18 | I AM SOME TEXT 19 | 20 | 21 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /themes/default-plain/pages/work.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
    11 |

    My work

    12 |

    OpenSource Contributions

    13 |

    Personal Projects

    14 |

    Client Work

    15 |
    16 | 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /themes/default-plain/post_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ post.title }} - {{ bc.meta._blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'post'; 7 | window.blogInfo.postId = '{{ post.id }}'; 8 | {% endblock %} 9 | 10 | {% block pagecontent %} 11 |
    12 | 13 | 14 |
    15 | 22 |
    23 | 24 |
    25 | 26 |
    27 | {{ post.html|safe }} 28 |
    29 | 30 | {% include 'snippets/post_bottom_navigation.html' %} 31 | {% include 'snippets/comment.html' %} 32 |
    33 | 34 | 35 | {% endblock %} 36 | -------------------------------------------------------------------------------- /themes/default-plain/snippets/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}{{ bc.meta.blog_name }}{% endblock title %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 28 | 29 | 30 | 31 | 32 | {% include 'snippets/navbar.html' %} 33 | 34 | {% block pagecontent %}{% endblock %} 35 | 36 | {% include 'snippets/footer.html' %} 37 | 38 | 39 | {% block javascript %} 40 | {% if bc.comment.isGithubAuth %} {% endif %} 41 | {% if bc.comment.isDisqus %} {% endif %} 42 | 43 | 44 | 45 | {% endblock javascript %} 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /themes/default-plain/snippets/comment.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 | 6 | {% if bc.comment.isGithubAuth and bc.comment.isGithub and not bc.comment.disabled %} 7 |
    8 |
    9 | let me know what you think about this post in the comments.😅 10 |
    11 |

    Leave a Comment

    12 |
    13 |
    14 |
    15 | 16 | 17 |
    18 | 19 |
    20 |
    21 |
    22 | 23 | 24 | {% elif bc.comment.isGithub and not bc.comment.disabled %} 25 | 28 | 29 | {% endif %} 30 | 31 | 32 |

    Comments

    33 |
    34 | 35 | 36 | 37 | {% if not bc.comment.disabled and not bc.comment.isDisqus %} 38 |
    39 |
    Load more
    40 |
    41 | {% endif %} 42 | 43 |
    44 | -------------------------------------------------------------------------------- /themes/default-plain/snippets/footer.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /themes/default-plain/snippets/navbar.html: -------------------------------------------------------------------------------- 1 | 4 |
    5 | 13 |
    14 | -------------------------------------------------------------------------------- /themes/default-plain/snippets/pagination.html: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | -------------------------------------------------------------------------------- /themes/default-plain/snippets/post_bottom_navigation.html: -------------------------------------------------------------------------------- 1 | 2 | 19 | -------------------------------------------------------------------------------- /themes/default-plain/static/css/comments.scss: -------------------------------------------------------------------------------- 1 | #comments_container { 2 | .avatar { 3 | padding-right: 1em; 4 | img { 5 | border-radius: 50%; 6 | } 7 | } 8 | .comment-meta { 9 | font-size: 0.6em; 10 | } 11 | } 12 | 13 | .goto-github { 14 | padding: 1em; 15 | background-color: #e3e3e3; 16 | } 17 | -------------------------------------------------------------------------------- /themes/default-plain/static/css/prism.css: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript&plugins=line-numbers+toolbar+show-language+copy-to-clipboard */ 2 | /** 3 | * okaidia theme for JavaScript, CSS and HTML 4 | * Loosely based on Monokai textmate theme by http://www.monokai.nl/ 5 | * @author ocodia 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: #f8f8f2; 11 | background: none; 12 | text-shadow: 0 1px rgba(0, 0, 0, 0.3); 13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | /* Code blocks */ 32 | pre[class*="language-"] { 33 | padding: 1em; 34 | margin: .5em 0; 35 | overflow: auto; 36 | border-radius: 0.3em; 37 | } 38 | 39 | :not(pre) > code[class*="language-"], 40 | pre[class*="language-"] { 41 | background: #272822; 42 | } 43 | 44 | /* Inline code */ 45 | :not(pre) > code[class*="language-"] { 46 | padding: .1em; 47 | border-radius: .3em; 48 | white-space: normal; 49 | } 50 | 51 | .token.comment, 52 | .token.prolog, 53 | .token.doctype, 54 | .token.cdata { 55 | color: slategray; 56 | } 57 | 58 | .token.punctuation { 59 | color: #f8f8f2; 60 | } 61 | 62 | .namespace { 63 | opacity: .7; 64 | } 65 | 66 | .token.property, 67 | .token.tag, 68 | .token.constant, 69 | .token.symbol, 70 | .token.deleted { 71 | color: #f92672; 72 | } 73 | 74 | .token.boolean, 75 | .token.number { 76 | color: #ae81ff; 77 | } 78 | 79 | .token.selector, 80 | .token.attr-name, 81 | .token.string, 82 | .token.char, 83 | .token.builtin, 84 | .token.inserted { 85 | color: #a6e22e; 86 | } 87 | 88 | .token.operator, 89 | .token.entity, 90 | .token.url, 91 | .language-css .token.string, 92 | .style .token.string, 93 | .token.variable { 94 | color: #f8f8f2; 95 | } 96 | 97 | .token.atrule, 98 | .token.attr-value, 99 | .token.function { 100 | color: #e6db74; 101 | } 102 | 103 | .token.keyword { 104 | color: #66d9ef; 105 | } 106 | 107 | .token.regex, 108 | .token.important { 109 | color: #fd971f; 110 | } 111 | 112 | .token.important, 113 | .token.bold { 114 | font-weight: bold; 115 | } 116 | .token.italic { 117 | font-style: italic; 118 | } 119 | 120 | .token.entity { 121 | cursor: help; 122 | } 123 | 124 | pre.line-numbers { 125 | position: relative; 126 | padding-left: 3.8em; 127 | counter-reset: linenumber; 128 | } 129 | 130 | pre.line-numbers > code { 131 | position: relative; 132 | } 133 | 134 | .line-numbers .line-numbers-rows { 135 | position: absolute; 136 | pointer-events: none; 137 | top: 0; 138 | font-size: 100%; 139 | left: -3.8em; 140 | width: 3em; /* works for line-numbers below 1000 lines */ 141 | letter-spacing: -1px; 142 | border-right: 1px solid #999; 143 | 144 | -webkit-user-select: none; 145 | -moz-user-select: none; 146 | -ms-user-select: none; 147 | user-select: none; 148 | 149 | } 150 | 151 | .line-numbers-rows > span { 152 | pointer-events: none; 153 | display: block; 154 | counter-increment: linenumber; 155 | } 156 | 157 | .line-numbers-rows > span:before { 158 | content: counter(linenumber); 159 | color: #999; 160 | display: block; 161 | padding-right: 0.8em; 162 | text-align: right; 163 | } 164 | pre.code-toolbar { 165 | position: relative; 166 | } 167 | 168 | pre.code-toolbar > .toolbar { 169 | position: absolute; 170 | top: .3em; 171 | right: .2em; 172 | transition: opacity 0.3s ease-in-out; 173 | opacity: 0; 174 | } 175 | 176 | pre.code-toolbar:hover > .toolbar { 177 | opacity: 1; 178 | } 179 | 180 | pre.code-toolbar > .toolbar .toolbar-item { 181 | display: inline-block; 182 | } 183 | 184 | pre.code-toolbar > .toolbar a { 185 | cursor: pointer; 186 | } 187 | 188 | pre.code-toolbar > .toolbar button { 189 | background: none; 190 | border: 0; 191 | color: inherit; 192 | font: inherit; 193 | line-height: normal; 194 | overflow: visible; 195 | padding: 0; 196 | -webkit-user-select: none; /* for button */ 197 | -moz-user-select: none; 198 | -ms-user-select: none; 199 | } 200 | 201 | pre.code-toolbar > .toolbar a, 202 | pre.code-toolbar > .toolbar button, 203 | pre.code-toolbar > .toolbar span { 204 | color: #bbb; 205 | font-size: .8em; 206 | padding: 0 .5em; 207 | background: #f5f2f0; 208 | background: rgba(224, 224, 224, 0.2); 209 | box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); 210 | border-radius: .5em; 211 | } 212 | 213 | pre.code-toolbar > .toolbar a:hover, 214 | pre.code-toolbar > .toolbar a:focus, 215 | pre.code-toolbar > .toolbar button:hover, 216 | pre.code-toolbar > .toolbar button:focus, 217 | pre.code-toolbar > .toolbar span:hover, 218 | pre.code-toolbar > .toolbar span:focus { 219 | color: inherit; 220 | text-decoration: none; 221 | } 222 | 223 | -------------------------------------------------------------------------------- /themes/default-plain/static/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/default-plain/static/images/favicon.png -------------------------------------------------------------------------------- /themes/default-plain/static/images/gravatar_wrapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/default-plain/static/images/gravatar_wrapper.png -------------------------------------------------------------------------------- /themes/default-plain/static/images/touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/default-plain/static/images/touch-icon.png -------------------------------------------------------------------------------- /themes/default-plain/static/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript for gitpushblog, webpack + init stuff 3 | */ 4 | 5 | import { initCommentSystem, initPostCategoryPage, displaySignOut } from './utils'; 6 | import { firebaseService } from './services'; 7 | 8 | // only imported assets will be available inside assets directory 9 | 10 | import '../css/main.scss'; 11 | import '../images/favicon.png'; 12 | import '../images/gravatar_wrapper.png'; 13 | 14 | // end of file imports 15 | 16 | const blogInfo = window.blogInfo; 17 | const bc = blogInfo.bc; 18 | 19 | // init firebase and display signout if signedin 20 | if(bc.comment.isGithubAuth){ 21 | firebaseService.init(); 22 | displaySignOut(); 23 | } 24 | 25 | switch(blogInfo.pageType){ 26 | case "index": 27 | break; 28 | case "post": 29 | initCommentSystem(); 30 | break; 31 | case "category": 32 | // you can enable async loading of category posts by toggling template_cat_posts 33 | // by default this is false 34 | if(!bc.others.template_cat_posts){ 35 | initPostCategoryPage(); 36 | } 37 | break; 38 | default: 39 | break; 40 | } 41 | 42 | 43 | /* 44 | * Add your custom javascript below 45 | */ 46 | 47 | console.log('wow!'); 48 | -------------------------------------------------------------------------------- /themes/default-plain/static/js/services.js: -------------------------------------------------------------------------------- 1 | const bc = window.blogInfo.bc; 2 | 3 | const firebaseInit = ()=>{ 4 | let config = bc.firebaseConfig; 5 | firebase.initializeApp(config); 6 | } 7 | 8 | const githubSignIn = ()=>{ 9 | let provider = new firebase.auth.GithubAuthProvider(); 10 | // this `scope` takes private repo permissions 11 | // need a lower permission than access to private repo. 12 | // any `scope` that only enables to comment on issues? 13 | provider.addScope('repo'); 14 | return new Promise((resolve,reject)=>{ 15 | firebase.auth().signInWithPopup(provider) 16 | .then(function(result) { 17 | let token = result.credential.accessToken; 18 | resolve(token); 19 | }) 20 | .catch(function(error) { 21 | // handle this, right now it's just copy paste from docs 22 | let errorCode = error.code; 23 | }); 24 | }); 25 | } 26 | 27 | const disqusInit = ()=>{ 28 | let disqus_config = function () { 29 | this.page.url = location.href; 30 | this.page.identifier = location.href; 31 | }; 32 | (function() { 33 | var d = document, s = d.createElement('script'); 34 | s.src = `https://${bc.comment.disqus_id}.disqus.com/embed.js`; 35 | s.setAttribute('data-timestamp', +new Date()); 36 | (d.head || d.body).appendChild(s); 37 | })(); 38 | } 39 | 40 | export const firebaseService = { 41 | init: firebaseInit, 42 | signIn: githubSignIn 43 | } 44 | 45 | export const disqusService = { 46 | init: disqusInit 47 | } 48 | -------------------------------------------------------------------------------- /themes/leonids-clone/_config.yml: -------------------------------------------------------------------------------- 1 | # Theme Settings [THESE ARE JUST SAMPLE FIELDS] 2 | # All these fields are available under the `tc`(theme config) object for all templates and client side javascript too 3 | 4 | title: "Theme Name" 5 | description: "Theme Description that can be long" 6 | google_verify: epFgX0s_0RM3Cds9ZBOLyaIUH-o # Put your Google Verification here 7 | google_analytics: UA-XXXXXXX-X # Put your Google Analytics code 8 | 9 | # Site Settings 10 | timezone: Asia/Kuala_Lumpur # optional 11 | 12 | # 13 | ################################### 14 | # Site Owner configuration 15 | #################################### 16 | # 17 | owner: 18 | name: Leonids 19 | avatar: leonids-logo.png 20 | job: "Student" 21 | bio: "the struggle is real" 22 | email: zourenyuan@gmail.com 23 | disqus-shortname: renyuanzblog 24 | twitter: geekodour #username 25 | facebook: #username 26 | google: 27 | plus: #username 28 | analytics: UA-651910-2 29 | verify: 30 | ad-client: 31 | ad-slot: 32 | bing-verify: 33 | github: geekodour #username 34 | stackoverflow: #123456/username from a "http://stackoverflow.com/users/123456/username" link 35 | linkedin: #username 36 | xing: #username 37 | instagram: pramoddubeyallahabad 38 | lastfm: #username 39 | tumblr: #username 40 | pinterest: #username 41 | foursquare: #username 42 | steam: #username 43 | dribbble: #username 44 | youtube: #username 45 | soundcloud: #username 46 | weibo: #username 47 | flickr: #username 48 | codepen: #username 49 | -------------------------------------------------------------------------------- /themes/leonids-clone/category_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ label.name }} - {{ bc.meta._blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'category'; 7 | window.blogInfo.label = '{{label.name}}'; 8 | {% endblock %} 9 | 10 | {% block pagecontent %} 11 |

    Posts tagged "{{ label.name }}"

    12 | {% if bc.others.template_cat_posts %} 13 | {% for post in posts %} 14 |
    15 | {{ post.title }} 16 |
    17 | {% endfor %} 18 | {% endif %} 19 | 20 | 21 | {% if not bc.others.template_cat_posts %} 22 |
    23 |
    Load more
    24 |
    25 | {% endif %} 26 | 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /themes/leonids-clone/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ bc.meta.blog_name }} 5 | {{ bc.meta.blog_description }} 6 | {{ ""|addbaseurl }} 7 | {% for post in posts %} 8 | 9 | {{ post.title }} 10 | {{ post.content }} 11 | {{ post.date }} 12 | {{ "/posts/"|addbaseurl }}{{ post.slug }} 13 | 14 | {% endfor %} 15 | 16 | 17 | -------------------------------------------------------------------------------- /themes/leonids-clone/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ bc.meta.blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'index'; 7 | {% endblock %} 8 | 9 | {% block pagecontent %} 10 | 11 | {% for post in posts %} 12 |
    13 |
    14 | 25 |

    26 | {{ post.title }} 27 |

    28 |
    29 |
    30 |

    31 | {{ post.body|truncate(200) }} 32 |

    33 |
    34 |
    35 | {% endfor %} 36 | 37 | {% include 'snippets/pagination.html' %} 38 | 39 | {% endblock %} 40 | -------------------------------------------------------------------------------- /themes/leonids-clone/pages/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
    11 |

    not found page

    12 | 404 page not found 13 |
    14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /themes/leonids-clone/pages/about.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 |
    10 | 13 | 14 |
    15 | I am about page 16 |
    17 | 18 | 19 |
    20 | 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /themes/leonids-clone/pages/standalone.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | title 12 | 13 | 14 | 15 | 16 | 17 | 18 | I AM SOME TEXT 19 | 20 | 21 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /themes/leonids-clone/pages/work.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | 3 | {% block inlinejavascript %} 4 | {{ super() }} 5 | window.blogInfo.pageType = 'page'; 6 | {% endblock %} 7 | 8 | {% block pagecontent %} 9 | 10 |
    11 |

    My work

    12 |

    OpenSource Contributions

    13 |

    Personal Projects

    14 |

    Client Work

    15 |
    16 | 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /themes/leonids-clone/post_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'snippets/base.html' %} 2 | {% block title %}{{ post.title }} - {{ bc.meta._blog_name }}{% endblock title %} 3 | 4 | {% block inlinejavascript %} 5 | {{ super() }} 6 | window.blogInfo.pageType = 'post'; 7 | window.blogInfo.postId = '{{ post.id }}'; 8 | {% endblock %} 9 | 10 | {% block pagecontent %} 11 |
    12 |
    13 |

    {{ post.title }}

    14 | 22 |
    23 | 24 |
    25 | {{ post.html|safe }} 26 |
    27 |
    28 | 29 | {% include 'snippets/post_bottom_navigation.html' %} 30 | {% include 'snippets/share_buttons.html' %} 31 | {% include 'snippets/comment.html' %} 32 | 33 | {% endblock %} 34 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}{{ bc.meta.blog_name }}{% endblock title %} 8 | 9 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | 31 |
    32 |
    33 |
    34 | {% include 'snippets/navbar.html' %} 35 |
    36 |
    37 |
    38 |
    39 | {% block pagecontent %}{% endblock %} 40 | {% include 'snippets/footer.html' %} 41 |
    42 |
    43 |
    44 | 45 | {% block javascript %} 46 | {% if bc.comment.isGithubAuth %} {% endif %} 47 | {% if bc.comment.isDisqus %} {% endif %} 48 | 49 | 50 | 51 | {% endblock javascript %} 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/comment.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 | 6 | {% if bc.comment.isGithubAuth and bc.comment.isGithub and not bc.comment.disabled %} 7 |
    8 |
    9 | let me know what you think about this post in the comments.😅 10 |
    11 |

    Leave a Comment

    12 |
    13 |
    14 |
    15 | 16 | 17 |
    18 | 19 |
    20 |
    21 |
    22 | 23 | 24 | {% elif bc.comment.isGithub and not bc.comment.disabled %} 25 | 28 | 29 | {% endif %} 30 | 31 | 32 |
    33 | 34 | 35 | 36 | {% if not bc.comment.disabled and not bc.comment.isDisqus %} 37 |
    38 |
    Load more
    39 |
    40 | {% endif %} 41 | 42 |
    43 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/footer.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/navbar.html: -------------------------------------------------------------------------------- 1 |
    2 | {{ bc.author }} 3 | {{ tc.owner.job }} 4 | {{ tc.owner.bio }} 5 | 23 | {% include 'snippets/social-links.html' %} 24 |
    25 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/pagination.html: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/post_bottom_navigation.html: -------------------------------------------------------------------------------- 1 | 2 | 19 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/share_buttons.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /themes/leonids-clone/snippets/social-links.html: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/components/_buttons.scss: -------------------------------------------------------------------------------- 1 | /* Buttons 2 | ========================================================================== */ 3 | 4 | // General 5 | .btn { 6 | display: inline-block; 7 | margin-bottom: 20px; 8 | padding: 8px 20px; 9 | font-size: 0.875em; 10 | font-family: $font-family-base; 11 | font-weight: 700; 12 | background-color: $primary; 13 | color: $white; 14 | border-width: 2px !important; 15 | border-style: solid !important; 16 | border-color: $primary; 17 | text-decoration: none !important; 18 | border-radius: 5px; 19 | &:visited { 20 | color: $white; 21 | border-color: $primary; 22 | } 23 | &:hover { 24 | background-color: $white; 25 | color: $primary; 26 | border-color: $primary; 27 | } 28 | } 29 | 30 | // Success button 31 | .btn-success { 32 | background-color: $success; 33 | color: $white; 34 | border-color: $success; 35 | &:visited { 36 | color: $white; 37 | border-color: $success; 38 | } 39 | &:hover { 40 | background-color: $white; 41 | color: $success; 42 | border-color: $success; 43 | } 44 | } 45 | 46 | // Warning button 47 | .btn-warning { 48 | background-color: $warning; 49 | color: $white; 50 | border-color: $warning; 51 | &:visited { 52 | color: $white; 53 | border-color: $warning; 54 | } 55 | &:hover { 56 | background-color: $white; 57 | color: $warning; 58 | border-color: $warning; 59 | } 60 | } 61 | 62 | // Danger button 63 | .btn-danger { 64 | background-color: $danger; 65 | color: $white; 66 | border-color: $danger; 67 | &:visited { 68 | color: $white; 69 | border-color: $danger; 70 | } 71 | &:hover { 72 | background-color: $white; 73 | color: $danger; 74 | border-color: $danger; 75 | } 76 | } 77 | 78 | // Information button 79 | .btn-info { 80 | background-color: $info; 81 | color: $white; 82 | border-color: $info; 83 | &:visited { 84 | border-color: $info; 85 | color: $white; 86 | } 87 | &:hover { 88 | background-color: $white; 89 | color: $info; 90 | border-color: $info; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/components/_global.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Global setting 3 | */ 4 | *, 5 | *:before, 6 | *:after { 7 | @include box-sizing; 8 | } 9 | .notice { 10 | border: 1px solid lighten($text-color, 45%); 11 | border-radius: 0.4em; 12 | padding: 0.5em 1em; 13 | } 14 | img { 15 | height: auto; 16 | max-width: 100%; 17 | } 18 | 19 | // Tables 20 | table, 21 | th, 22 | td { 23 | border: none; 24 | } 25 | .table { 26 | display: table; 27 | } 28 | .table-cell { 29 | display: table-cell; 30 | } 31 | .table-top { 32 | vertical-align: top; 33 | } 34 | .table-middle { 35 | vertical-align: middle; 36 | } 37 | .table-bottom { 38 | vertical-align: bottom; 39 | } 40 | table { 41 | width: 100%; 42 | display: table; 43 | &.bordered > thead > tr, 44 | &.bordered > tbody > tr { 45 | border-bottom: 1px solid $table-border-color; 46 | } 47 | &.striped > tbody { 48 | > tr:nth-child(odd) { 49 | background-color: $table-striped-color; 50 | } 51 | > tr > td { 52 | border-radius: 0; 53 | } 54 | } 55 | &.highlight > tbody > tr { 56 | @include transition(background-color .25s ease); 57 | &:hover { 58 | background-color: $table-striped-color; 59 | } 60 | } 61 | &.centered { 62 | thead tr th, 63 | tbody tr td, 64 | tfoot tr td { 65 | text-align: center; 66 | } 67 | } 68 | } 69 | thead { 70 | border-bottom: 1px solid $table-border-color; 71 | } 72 | td, 73 | th { 74 | padding: 15px 5px; 75 | display: table-cell; 76 | text-align: left; 77 | vertical-align: middle; 78 | border-radius: 2px; 79 | } 80 | tfoot { 81 | border-top: 1px solid $table-border-color; 82 | } 83 | 84 | // Global transition 85 | b, 86 | i, 87 | strong, 88 | em, 89 | blockquote, 90 | p, 91 | q, 92 | span, 93 | figure, 94 | img, 95 | h1, 96 | h2, 97 | header, 98 | input, 99 | a { 100 | @include transition(all .1s ease); 101 | } 102 | 103 | // Footer 104 | footer { 105 | text-align: center; 106 | padding: 3em 0; 107 | .heart-icon { 108 | color: $danger; 109 | text-shadow: 0 0 5px $white, 0 0 10px $danger; 110 | } 111 | } 112 | .related-articles { 113 | margin-top: 2em; 114 | h4 { 115 | font-family: $font-family-base; 116 | } 117 | ul { 118 | margin: 0; 119 | padding: 0; 120 | list-style: none; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/components/_grid.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Grid 3 | */ 4 | 5 | // Container 6 | .container { 7 | margin: 0 auto; 8 | max-width: 1280px; 9 | width: 90%; 10 | } 11 | @include media-query($medium-screen) { 12 | .container { 13 | width: 85%; 14 | } 15 | } 16 | @include media-query($large-screen) { 17 | .container { 18 | width: 70%; 19 | } 20 | } 21 | .container .row { 22 | margin-left: (-1 * $gutter-width / 2); 23 | margin-right: (-1 * $gutter-width / 2); 24 | } 25 | 26 | // Section 27 | .section { 28 | padding-top: 1rem; 29 | padding-bottom: 1rem; 30 | 31 | &.no-pad { 32 | padding: 0; 33 | } 34 | &.no-pad-bot { 35 | padding-bottom: 0; 36 | } 37 | &.no-pad-top { 38 | padding-top: 0; 39 | } 40 | } 41 | 42 | // Row and colum 43 | .row { 44 | margin-left: auto; 45 | margin-right: auto; 46 | 47 | // Clear floating children 48 | &:after { 49 | content: ""; 50 | display: table; 51 | clear: both; 52 | } 53 | 54 | .col { 55 | float: left; 56 | @include box-sizing(border-box); 57 | display:block; 58 | vertical-align:top; 59 | width:100%; 60 | 61 | $i: 1; 62 | @while $i <= $num-cols { 63 | $perc: unquote((100 / ($num-cols / $i)) + "%"); 64 | &.s#{$i} { 65 | width: $perc; 66 | margin-left: 0; 67 | } 68 | $i: $i + 1; 69 | } 70 | $i: 1; 71 | @while $i <= $num-cols { 72 | $perc: unquote((100 / ($num-cols / $i)) + "%"); 73 | &.offset-s#{$i} { 74 | margin-left: $perc; 75 | } 76 | $i: $i + 1; 77 | } 78 | 79 | 80 | @include media-query($small-screen) { 81 | 82 | $i: 1; 83 | @while $i <= $num-cols { 84 | $perc: unquote((100 / ($num-cols / $i)) + "%"); 85 | &.m#{$i} { 86 | width: $perc; 87 | margin-left: 0; 88 | } 89 | $i: $i + 1; 90 | } 91 | $i: 1; 92 | @while $i <= $num-cols { 93 | $perc: unquote((100 / ($num-cols / $i)) + "%"); 94 | &.offset-m#{$i} { 95 | margin-left: $perc; 96 | } 97 | $i: $i + 1; 98 | } 99 | 100 | } 101 | 102 | @include media-query($medium-screen) { 103 | 104 | $i: 1; 105 | @while $i <= $num-cols { 106 | $perc: unquote((100 / ($num-cols / $i)) + "%"); 107 | &.l#{$i} { 108 | width: $perc; 109 | margin-left: 0; 110 | } 111 | $i: $i + 1; 112 | } 113 | $i: 1; 114 | @while $i <= $num-cols { 115 | $perc: unquote((100 / ($num-cols / $i)) + "%"); 116 | &.offset-l#{$i} { 117 | margin-left: $perc; 118 | } 119 | $i: $i + 1; 120 | } 121 | 122 | } 123 | 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/components/_helpers.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Helpers 3 | */ 4 | 5 | // Displays 6 | .block { display: block } 7 | .inline-block { display: inline-block } 8 | 9 | .hidden-md { 10 | display: none; 11 | @include media-query($medium-screen) { 12 | display: inline-block; 13 | } 14 | } 15 | 16 | .radius-box { 17 | border-radius: 10px; 18 | } 19 | 20 | .radius-ls { 21 | border-bottom-left-radius: 3px; 22 | border-top-left-radius: 3px; 23 | } 24 | .radius-rs { 25 | border-bottom-right-radius: 3px; 26 | border-top-right-radius: 3px; 27 | } 28 | 29 | .radius-l1 { 30 | border-bottom-left-radius: 10px; 31 | border-top-left-radius: 10px; 32 | } 33 | .radius-r1 { 34 | border-bottom-right-radius: 10px; 35 | border-top-right-radius: 10px; 36 | } 37 | 38 | // Margin helpers 39 | .m0 { margin: 0 } 40 | .mt0 { margin-top: 0 } 41 | .mr0 { margin-right: 0 } 42 | .mb0 { margin-bottom: 0 } 43 | .ml0 { margin-left: 0 } 44 | 45 | .ms { margin: .25em } 46 | .mts { margin-top: .25em } 47 | .mbs { margin-bottom: .25em } 48 | .mrs { margin-right: .25em } 49 | .mls { margin-left: .25em } 50 | 51 | .mm { margin: .5em } 52 | .mtm { margin-top: .5em } 53 | .mbm { margin-bottom: .5em } 54 | .mrm { margin-right: .5em } 55 | .mlm { margin-left: .5em } 56 | 57 | .m1 { margin: $base-space-unit } 58 | .mt1 { margin-top: $base-space-unit } 59 | .mb1 { margin-bottom: $base-space-unit } 60 | .mr1 { margin-right: $base-space-unit } 61 | .ml1 { margin-left: $base-space-unit } 62 | 63 | .m2 { margin: $base-space-unit*2 } 64 | .mt2 { margin-top: $base-space-unit*2 } 65 | .mb2 { margin-bottom: $base-space-unit*2 } 66 | .mr2 { margin-right: $base-space-unit*2 } 67 | .ml2 { margin-left: $base-space-unit*2 } 68 | 69 | // Padding helpers 70 | .p0 { padding: 0 } 71 | .pt0 { padding-top: 0 } 72 | .pr0 { padding-right: 0 } 73 | .pb0 { padding-bottom: 0 } 74 | .pl0 { padding-left: 0 } 75 | 76 | .ps { padding: .25em } 77 | .pts { padding-top: .25em } 78 | .pbs { padding-bottom: .25em } 79 | .prs { padding-right: .25em } 80 | .pls { padding-left: .25em } 81 | 82 | .pm { padding: .5em } 83 | .ptm { padding-top: .5em } 84 | .pbm { padding-bottom: .5em } 85 | .prm { padding-right: .5em } 86 | .plm { padding-left: .5em } 87 | 88 | .p1 { padding: 1em } 89 | .pt1 { padding-top: 1em } 90 | .pr1 { padding-right: 1em } 91 | .pb1 { padding-bottom: 1em } 92 | .pl1 { padding-left: 1em } 93 | 94 | .p2 { padding: 1em*2 } 95 | .pt2 { padding-top: 1em*2 } 96 | .pr2 { padding-right: 1em*2 } 97 | .pb2 { padding-bottom: 1em*2 } 98 | .pl2 { padding-left: 1em*2 } 99 | 100 | .pb5 { padding-bottom: 1em*5 } 101 | 102 | // Padding small 103 | .pads { padding: .25em } 104 | 105 | // Padding medium 106 | .padm { padding: .5em } 107 | 108 | // Padding large 109 | .padl { padding: 1em } 110 | 111 | // Padding small left :: right 112 | .padsx { 113 | padding-left: .25em; 114 | padding-right: .25em; 115 | } 116 | 117 | // Padding medium left :: right 118 | .padmx { 119 | padding-left: .5em; 120 | padding-right: .5em; 121 | } 122 | 123 | // Padding large left :: right 124 | .padlx { 125 | padding-left: 1em; 126 | padding-right: 1em; 127 | } 128 | 129 | // Padding small top :: bottom 130 | .padsy { 131 | padding-top: .25em; 132 | padding-bottom: .25em; 133 | } 134 | 135 | // Padding medium top :: bottom 136 | .padmy { 137 | padding-top: .5em; 138 | padding-bottom: .5em; 139 | } 140 | 141 | // Padding large top :: bottom 142 | .padly { 143 | padding-top: 1em; 144 | padding-bottom: 1em; 145 | } 146 | 147 | // Colors helpers 148 | .primary-text-color { 149 | color: $primary; 150 | } 151 | 152 | .primary-bg-color { 153 | background-color: $primary; 154 | } 155 | 156 | .secondary-text-color { 157 | color: $secondary; 158 | } 159 | 160 | .secondary-bg-color { 161 | background-color: $secondary; 162 | } 163 | 164 | .success-text-color { 165 | color: $success; 166 | } 167 | 168 | .success-bg-color { 169 | background-color: $success; 170 | } 171 | 172 | .danger-text-color { 173 | color: $danger; 174 | } 175 | 176 | .danger-bg-color { 177 | background-color: $danger; 178 | } 179 | 180 | .info-text-color { 181 | color: $info; 182 | } 183 | 184 | .info-bg-color { 185 | background-color: $info; 186 | } 187 | 188 | .warning-text-color { 189 | color: $warning; 190 | } 191 | 192 | .warning-bg-color { 193 | background-color: $warning; 194 | } 195 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/components/_syntax-highlighting.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Syntax highlighting 3 | ========================================================================== */ 4 | 5 | 6 | pre, code { 7 | font-family: $font-family-monospace; 8 | color: #525252; 9 | font-size: 0.9em; 10 | background-color: #f8f8f8; 11 | font-size: ($font-size-base - 3); 12 | } 13 | code { 14 | color: #e96900; 15 | border-radius: 2px; 16 | white-space: nowrap; 17 | } 18 | 19 | 20 | pre { // only apply for code blocks 21 | overflow: auto; 22 | display: block; 23 | padding: 1em; 24 | margin: 0 0 1em; 25 | line-height: $base-line-height * 0.925; 26 | word-break: break-all; 27 | word-wrap: break-word; 28 | border-radius: 0; 29 | font-weight: normal; 30 | } 31 | pre code { 32 | background: transparent; 33 | white-space: pre; 34 | overflow: auto; 35 | word-wrap: normal; 36 | color: #525252; 37 | span { 38 | word-break: break-all; 39 | } 40 | } 41 | .highlight { 42 | margin: 0; 43 | pre { 44 | position: relative; 45 | } 46 | pre code { 47 | color: #525252; 48 | &::before { 49 | content: attr(data-lang); 50 | position: absolute; 51 | top: 0; 52 | right: 0; 53 | color: #ccc; 54 | text-align: right; 55 | text-transform: uppercase; 56 | font-size: 0.85em; 57 | padding: 5px 10px 0; 58 | line-height: 20px; 59 | height: 20px; 60 | font-weight: 600; 61 | } 62 | } 63 | .hll { background-color: #ffffcc } 64 | .c { color: #B0B2B0; font-style: italic } /* Comment */ 65 | .err { } /* Error */ 66 | .k { color: #AA22FF; font-weight: bold } /* Keyword */ 67 | .o { color: #666666 } /* Operator */ 68 | .cm { color: #B0B2B0; font-style: italic } /* Comment.Multiline */ 69 | .cp { color: #B0B2B0 } /* Comment.Preproc */ 70 | .c1 { color: #B0B2B0; font-style: italic } /* Comment.Single */ 71 | .cs { color: #B0B2B0; font-weight: bold } /* Comment.Special */ 72 | .gd { color: #A00000 } /* Generic.Deleted */ 73 | .ge { font-style: italic } /* Generic.Emph */ 74 | .gr { color: #FF0000 } /* Generic.Error */ 75 | .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 76 | .gi { color: #00A000 } /* Generic.Inserted */ 77 | .go { color: #808080 } /* Generic.Output */ 78 | .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 79 | .gs { font-weight: bold } /* Generic.Strong */ 80 | .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 81 | .gt { color: #0040D0 } /* Generic.Traceback */ 82 | .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */ 83 | .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */ 84 | .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */ 85 | .kp { color: #AA22FF } /* Keyword.Pseudo */ 86 | .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */ 87 | .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */ 88 | .m { color: #666666 } /* Literal.Number */ 89 | .s { color: #BB4444 } /* Literal.String */ 90 | .na { color: #BB4444 } /* Name.Attribute */ 91 | .nb { color: #AA22FF } /* Name.Builtin */ 92 | .nc { color: #0000FF } /* Name.Class */ 93 | .no { color: #880000 } /* Name.Constant */ 94 | .nd { color: #AA22FF } /* Name.Decorator */ 95 | .ni { color: #999999; font-weight: bold } /* Name.Entity */ 96 | .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 97 | .nf { color: #00A000 } /* Name.Function */ 98 | .nl { color: #A0A000 } /* Name.Label */ 99 | .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 100 | .nt { color: #008000; font-weight: bold } /* Name.Tag */ 101 | .nv { color: #B8860B } /* Name.Variable */ 102 | .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 103 | .w { color: #bbbbbb } /* Text.Whitespace */ 104 | .mf { color: #666666 } /* Literal.Number.Float */ 105 | .mh { color: #666666 } /* Literal.Number.Hex */ 106 | .mi { color: #666666 } /* Literal.Number.Integer */ 107 | .mo { color: #666666 } /* Literal.Number.Oct */ 108 | .sb { color: #BB4444 } /* Literal.String.Backtick */ 109 | .sc { color: #BB4444 } /* Literal.String.Char */ 110 | .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */ 111 | .s2 { color: #BB4444 } /* Literal.String.Double */ 112 | .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 113 | .sh { color: #BB4444 } /* Literal.String.Heredoc */ 114 | .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 115 | .sx { color: #008000 } /* Literal.String.Other */ 116 | .sr { color: #BB6688 } /* Literal.String.Regex */ 117 | .s1 { color: #BB4444 } /* Literal.String.Single */ 118 | .ss { color: #B8860B } /* Literal.String.Symbol */ 119 | .bp { color: #AA22FF } /* Name.Builtin.Pseudo */ 120 | .vc { color: #B8860B } /* Name.Variable.Class */ 121 | .vg { color: #B8860B } /* Name.Variable.Global */ 122 | .vi { color: #B8860B } /* Name.Variable.Instance */ 123 | .il { color: #666666 } /* Literal.Number.Integer.Long */ 124 | } 125 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/components/_typography.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Typography 3 | ========================================================================== */ 4 | 5 | // 6 | // Global 7 | // 8 | 9 | html { 10 | line-height: $base-line-height; 11 | font-family: $font-family-base; 12 | font-weight: normal; 13 | color: $text-color; 14 | -webkit-font-smoothing: antialiased; 15 | text-rendering: optimizeLegibility; 16 | font-size: $font-size-base; 17 | } 18 | 19 | // 20 | // Blockquote 21 | // 22 | 23 | blockquote { 24 | display: block; 25 | position: relative; 26 | padding-left: 20px; 27 | font-style: italic; 28 | border-left: 5px solid $secondary; 29 | } 30 | 31 | // 32 | // Links 33 | // 34 | 35 | a { 36 | text-decoration: none; 37 | color: $primary; 38 | &:hover, 39 | &:focus { 40 | color: lighten($primary, 14%); 41 | text-decoration: none; 42 | } 43 | } 44 | 45 | // 46 | // Header Styles 47 | // 48 | 49 | h1, h2, h3, h4, h5, h6 { 50 | font-weight: 600; 51 | line-height: 1.7; 52 | } 53 | 54 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { 55 | font-weight: inherit; 56 | color: $text-color; 57 | &:hover, 58 | &:focus { 59 | color: lighten($text-color, 24%); 60 | } 61 | } 62 | h1 { font-size: $font-size-h1; margin: ($font-size-h1 / 2) 0 ($font-size-h1 / 2.5) 0;} 63 | h2 { font-size: $font-size-h2; margin: ($font-size-h2 / 2) 0 ($font-size-h2 / 2.5) 0;} 64 | h3 { font-size: $font-size-h3; margin: ($font-size-h3 / 2) 0 ($font-size-h3 / 2.5) 0;} 65 | h4 { font-size: $font-size-h4; margin: ($font-size-h4 / 2) 0 ($font-size-h4 / 2.5) 0;} 66 | h5 { font-size: $font-size-h5; margin: ($font-size-h5 / 2) 0 ($font-size-h5 / 2.5) 0;} 67 | h6 { font-size: $font-size-h6; margin: ($font-size-h6 / 2) 0 ($font-size-h6 / 2.5) 0; text-transform: uppercase;} 68 | 69 | // 70 | // Horizontal rules 71 | // 72 | 73 | hr { 74 | margin-top: $spacer-y; 75 | margin-bottom: $spacer-y; 76 | border: 0; 77 | border-top: $hr-border-width solid $hr-border-color; 78 | } 79 | 80 | // 81 | // Text Styles 82 | // 83 | 84 | em { font-style: italic; } 85 | 86 | strong { font-weight: 600; } 87 | 88 | small, 89 | .small { 90 | font-size: 80%; 91 | font-weight: normal; 92 | } 93 | 94 | p { 95 | margin: 1.2em 0; 96 | word-spacing: 0.05em; 97 | line-height: 1.6em; 98 | } 99 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/components/_variables.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Global Variables 3 | */ 4 | 5 | // Google font import 6 | @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:600,400,400italic|Roboto+Mono); 7 | 8 | // Custom variables 9 | 10 | // Spacing 11 | // 12 | // Control the default styling of most Bootstrap elements by modifying these 13 | // variables. Mostly focused on spacing. 14 | 15 | $spacer: 1rem !default; 16 | $spacer-x: $spacer !default; 17 | $spacer-y: $spacer !default; 18 | $border-width: .0625rem !default; 19 | 20 | // Typography 21 | // 22 | // Font, line-height, and color for body text, headings, and more. 23 | 24 | $font-family-sans-serif: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif !default; 25 | $font-family-serif: Georgia, "Times New Roman", Times, serif !default; 26 | $font-family-monospace: "Roboto Mono", "Courier New", monospace !default; 27 | $font-family-base: $font-family-sans-serif !default; 28 | 29 | // Pixel value used to responsively scale all typography. Applied to the `` element. 30 | $font-size-root: 15px !default; 31 | 32 | $font-size-base: $font-size-root !default; 33 | $font-size-lg: $font-size-root * 1.25 !default; 34 | $font-size-sm: $font-size-root * 0.875 !default; 35 | $font-size-xs: $font-size-root * 0.75 !default; 36 | 37 | $font-size-h1: 2rem !default; 38 | $font-size-h2: 1.75rem !default; 39 | $font-size-h3: 1.5rem !default; 40 | $font-size-h4: 1.25rem !default; 41 | $font-size-h5: 1.15rem !default; 42 | $font-size-h6: 1rem !default; 43 | 44 | $base-line-height: 1.5; 45 | $base-space-unit: 1.5em; 46 | 47 | $hr-border-color: rgba(0,0,0,.1) !default; 48 | $hr-border-width: $border-width; 49 | 50 | // 51 | // Colors 52 | // 53 | 54 | $text-color: rgba(0, 0, 0, 0.87) !default; 55 | $background-color: #f5f5f5; 56 | 57 | $white: #fff; 58 | $primary: #42b983; 59 | $secondary: #8d7edc; 60 | $success: #65e892; 61 | $danger: #f83e4b; 62 | $warning: #F5A623; 63 | $info: #09ABF6; 64 | 65 | // Tables 66 | $table-border-color: #d0d0d0 !default; 67 | $table-striped-color: #f2f2f2 !default; 68 | 69 | // Grid Variables 70 | $num-cols: 12 !default; 71 | $gutter-width: 1.5rem !default; 72 | $element-top-margin: $gutter-width/3 !default; 73 | $element-bottom-margin: ($gutter-width*2)/3 !default; 74 | 75 | // Media Query Ranges 76 | $small-screen: 600px !default; 77 | $medium-screen: 992px !default; 78 | $large-screen: 1200px !default; 79 | $larger-screen: 1600px !default; 80 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/main.scss: -------------------------------------------------------------------------------- 1 | @import 'prism.css'; 2 | @import 'font-awesome.min.css'; 3 | @charset "UTF-8"; 4 | 5 | // Mixins 6 | @import "components/mixins"; 7 | 8 | // Variables 9 | @import "components/variables"; 10 | 11 | // Reset 12 | @import "components/normalize"; 13 | 14 | // Components 15 | @import "components/global"; 16 | @import "components/helpers"; 17 | @import "components/grid"; 18 | @import "components/typography"; 19 | @import "components/buttons"; 20 | @import "components/syntax-highlighting"; 21 | 22 | // Pages styling 23 | @import "pages/layout"; 24 | @import "pages/tags"; 25 | @import "pages/archive"; 26 | @import "pages/post"; 27 | 28 | /* 29 | * custom scss 30 | */ 31 | section.post { 32 | margin : 0; 33 | border-bottom: 1px dotted #454545; 34 | } 35 | 36 | .post-content { 37 | word-wrap: break-word; 38 | } 39 | .goto-github { 40 | padding: 1em; 41 | background-color: #f60; 42 | a { 43 | color: #fff; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/pages/_archive.scss: -------------------------------------------------------------------------------- 1 | .archive { 2 | #timeline { 3 | position: relative; 4 | &:before { 5 | content: ''; 6 | position: absolute; 7 | top: 0; 8 | left: -2px; 9 | height: 100%; 10 | width: 4px; 11 | background: $background-color; 12 | } 13 | &:after { 14 | content: ""; 15 | display: table; 16 | clear: both; 17 | } 18 | } 19 | 20 | .archive-title { 21 | position: relative; 22 | margin: 2em auto 1em; 23 | .archive-year { 24 | margin-left: 1em; 25 | &:before { 26 | content: " "; 27 | position: absolute; 28 | left: 0; 29 | top: 50%; 30 | margin-left: -4px; 31 | margin-top: -4px; 32 | width: 8px; 33 | height: 8px; 34 | background: #bbb; 35 | border-radius: 50%; 36 | } 37 | } 38 | } 39 | 40 | 41 | ul { 42 | list-style: none; 43 | li { 44 | margin: 1em auto; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/pages/_layout.scss: -------------------------------------------------------------------------------- 1 | /* LAYOUT CSS */ 2 | .cover { 3 | background-color: $background-color; 4 | position: fixed; 5 | text-align: center; 6 | width: 100%; 7 | min-height: 400px; 8 | padding: 30px 15px 20px; 9 | z-index: 1; 10 | @include media-query($small-screen) { 11 | background-position: center; 12 | padding: 30px; 13 | } 14 | @include media-query($medium-screen) { 15 | height: 100vh; 16 | position: initial; 17 | width: 100%; 18 | } 19 | } 20 | .cover-card { 21 | color: $text-color; 22 | padding: 0 30px; 23 | .avatar { 24 | border-radius: 50%; 25 | width: 100px; 26 | height: 100px; 27 | float: none; 28 | } 29 | .author_name { 30 | display: block; 31 | color: #F36170; 32 | font-size: 1.75em; 33 | text-transform: lowercase; 34 | } 35 | .author_job { 36 | display: block; 37 | color: $secondary; 38 | font-size: 0.8em; 39 | font-weight: 700; 40 | text-transform: uppercase; 41 | margin: -5px auto 10px; 42 | } 43 | .author_bio { 44 | font-size: 90%; 45 | display: block; 46 | } 47 | @include media-query($medium-screen) { 48 | text-align: right; 49 | margin: 0 auto; 50 | padding: 0 0px 80px; 51 | } 52 | } 53 | .social-links { 54 | margin-top: 0.5em; 55 | ul { 56 | margin: 0; 57 | padding: 0; 58 | li { 59 | list-style: none; 60 | display: inline-block; 61 | margin-left: 1em; 62 | a.social-link-item { 63 | color: $secondary; 64 | &:hover, 65 | &:focus { 66 | color: lighten($secondary, 14%); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | .nav-list { 73 | margin: 0; 74 | padding: 0; 75 | list-style: none; 76 | .nav-item { 77 | display: inline-block; 78 | *display: inline; 79 | zoom: 1; 80 | & a { 81 | margin-top: 1em; 82 | text-transform: lowercase; 83 | font-size: 85%; 84 | color: $secondary; 85 | &:hover, 86 | &:focus { 87 | color: lighten($secondary, 14%); 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/pages/_post.scss: -------------------------------------------------------------------------------- 1 | // Post listing 2 | .post-listing { 3 | background-color: $white; 4 | position: absolute; 5 | top: 400px; 6 | z-index: 233; 7 | width: 100%; 8 | padding: 20px 20px 0; 9 | -webkit-transform: translate3d(0,0,1px); 10 | transform: translate3d(0,0,1px); 11 | @include media-query($small-screen) { 12 | padding: 50px 30px 0; 13 | } 14 | @include media-query($medium-screen) { 15 | height: 100vh; 16 | overflow-y: scroll; 17 | position: initial; 18 | top: 0; 19 | } 20 | } 21 | 22 | .image-credit { 23 | float: right; 24 | font-weight: bold; 25 | font-style: italic; 26 | color: $info; 27 | font-size: 13px; 28 | padding-right: 20px; 29 | } 30 | 31 | // Post Section 32 | section.post { 33 | margin-bottom: 80px; 34 | } 35 | 36 | // Back home button 37 | 38 | .back-home a { 39 | font-size: 13px; 40 | font-weight: bold; 41 | color: $info; 42 | border: 1px solid lighten($text-color, 45%); 43 | border-radius: 0.4em; 44 | padding: 0.5em 1em; 45 | } 46 | 47 | // Post title 48 | .post-title { 49 | 50 | } 51 | 52 | .post-title-link { 53 | color: $primary; 54 | font-size: 14px; 55 | margin-left: 10px; 56 | &:hover, 57 | &:focus { 58 | color: lighten($primary, 14%); 59 | } 60 | } 61 | 62 | // Post meta 63 | .post-meta { 64 | font-size: 13px; 65 | font-weight: bold; 66 | .post-date { 67 | color: $secondary; 68 | } 69 | .post-author { 70 | text-transform: uppercase; 71 | color: $warning; 72 | } 73 | .post-cat { 74 | text-transform: uppercase; 75 | color: $warning; 76 | } 77 | .read-time { 78 | color: $primary; 79 | } 80 | } 81 | 82 | // Read more buttons 83 | 84 | a.read-more { 85 | padding: 5px 8px; 86 | } 87 | 88 | // Post content 89 | 90 | #post { 91 | padding-bottom: 50px; 92 | .post-header { 93 | margin: 0 auto 50px; 94 | } 95 | } 96 | 97 | #post h1 { 98 | margin: 0.5em 0 1em; 99 | } 100 | #post h2 { 101 | margin: 2em 0 0.8em; 102 | padding-bottom: 0.7em; 103 | border-bottom: 1px solid #ddd; 104 | } 105 | #post h3 { 106 | margin: 1.75em 0 1.2em; 107 | position: relative; 108 | } 109 | 110 | #page { 111 | padding-bottom: 50px; 112 | min-height: 70vh; 113 | .page-header { 114 | margin: 0 auto 50px; 115 | } 116 | } 117 | 118 | .post-navigation { 119 | background-color: #f6f6f6; 120 | @include box-shadow; 121 | } 122 | .leonids-icon { 123 | margin: 0 auto; 124 | padding: 20px 30px; 125 | text-align: center; 126 | color: $warning; 127 | font-size: 16px; 128 | line-height: 16px; 129 | } 130 | .post-nav-prev, 131 | .post-nav-next { 132 | min-height: 10px; 133 | width: 100%; 134 | } 135 | .post-nav-next { 136 | text-align: right; 137 | } 138 | .post-nav-btn { 139 | width: 100%; 140 | padding: 20px 30px; 141 | .post-nav-text { 142 | font-size: 16px; 143 | line-height: 16px; 144 | font-weight: bold; 145 | } 146 | .table-cell { 147 | vertical-align: middle; 148 | } 149 | } 150 | .post-image-feature { 151 | margin-bottom: 40px; 152 | .feature-image { 153 | width: 100%; 154 | max-height: 500px; 155 | } 156 | } 157 | 158 | // Shares Buttons 159 | .share-buttons { 160 | padding-top: 1em; 161 | border-top: 1px solid #ddd; 162 | ul { 163 | margin: 0; 164 | padding: 0; 165 | list-style: none; 166 | li { 167 | display: inline-block; 168 | margin-right: 0.5em; 169 | span { 170 | display: none; 171 | @include media-query($small-screen) { 172 | display: inline; 173 | margin: 0.5em; 174 | } 175 | } 176 | } 177 | } 178 | } 179 | .twitter { 180 | background-color: #77bcf1; 181 | color: $white; 182 | border-color: #77bcf1; 183 | &:visited { 184 | color: $white; 185 | border-color: #77bcf1; 186 | } 187 | &:hover { 188 | background-color: $white; 189 | color: #77bcf1; 190 | border-color: #77bcf1; 191 | } 192 | } 193 | .facebook { 194 | background-color: #627aac; 195 | color: $white; 196 | border-color: #627aac; 197 | &:visited { 198 | color: $white; 199 | border-color: #627aac; 200 | } 201 | &:hover { 202 | background-color: $white; 203 | color: #627aac; 204 | border-color: #627aac; 205 | } 206 | } 207 | .google-plus { 208 | background-color: #e36f60; 209 | color: $white; 210 | border-color: #e36f60; 211 | &:visited { 212 | color: $white; 213 | border-color: #e36f60; 214 | } 215 | &:hover { 216 | background-color: $white; 217 | color: #e36f60; 218 | border-color: #e36f60; 219 | } 220 | } 221 | .hacker-news { 222 | background-color: #f60; 223 | color: $white; 224 | border-color: #f60; 225 | &:visited { 226 | color: $white; 227 | border-color: #f60; 228 | } 229 | &:hover { 230 | background-color: $white; 231 | color: #f60; 232 | border-color: #f60; 233 | } 234 | } 235 | .reddit { 236 | background-color: #5f99cf; 237 | color: $white; 238 | border-color: #5f99cf; 239 | &:visited { 240 | color: $white; 241 | border-color: #5f99cf; 242 | } 243 | &:hover { 244 | background-color: $white; 245 | color: #5f99cf; 246 | border-color: #5f99cf; 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/pages/_tags.scss: -------------------------------------------------------------------------------- 1 | ul.tag-cloud { 2 | padding: 2em 0 3em; 3 | margin: 0; 4 | overflow: hidden; 5 | list-style: none; 6 | 7 | li { 8 | display: inline-block; 9 | margin-right: .5em; 10 | a.post-tag { 11 | border-radius: 0.2em; 12 | } 13 | } 14 | } 15 | 16 | .tag-list { 17 | .tag-group { 18 | margin-bottom: 2em; 19 | .tag-group-title { 20 | color: $warning; 21 | text-transform: capitalize; 22 | } 23 | 24 | .tag-item { 25 | padding-left: 1em; 26 | margin-bottom: .5em; 27 | a { 28 | color: $text-color; 29 | &:hover, 30 | &:focus { 31 | color: lighten($text-color, 24%); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | .cat-list { 39 | .cat-group { 40 | margin-bottom: 2em; 41 | .cat-group-title { 42 | color: $warning; 43 | text-transform: capitalize; 44 | } 45 | 46 | .cat-item { 47 | padding-left: 1em; 48 | margin-bottom: .5em; 49 | a { 50 | color: $danger; 51 | &:hover, 52 | &:focus { 53 | color: lighten($danger, 24%); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/css/prism.css: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript&plugins=line-numbers+toolbar+show-language+copy-to-clipboard */ 2 | /** 3 | * okaidia theme for JavaScript, CSS and HTML 4 | * Loosely based on Monokai textmate theme by http://www.monokai.nl/ 5 | * @author ocodia 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: #f8f8f2; 11 | background: none; 12 | text-shadow: 0 1px rgba(0, 0, 0, 0.3); 13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | /* Code blocks */ 32 | pre[class*="language-"] { 33 | padding: 1em; 34 | margin: .5em 0; 35 | overflow: auto; 36 | border-radius: 0.3em; 37 | } 38 | 39 | :not(pre) > code[class*="language-"], 40 | pre[class*="language-"] { 41 | background: #272822; 42 | } 43 | 44 | /* Inline code */ 45 | :not(pre) > code[class*="language-"] { 46 | padding: .1em; 47 | border-radius: .3em; 48 | white-space: normal; 49 | } 50 | 51 | .token.comment, 52 | .token.prolog, 53 | .token.doctype, 54 | .token.cdata { 55 | color: slategray; 56 | } 57 | 58 | .token.punctuation { 59 | color: #f8f8f2; 60 | } 61 | 62 | .namespace { 63 | opacity: .7; 64 | } 65 | 66 | .token.property, 67 | .token.tag, 68 | .token.constant, 69 | .token.symbol, 70 | .token.deleted { 71 | color: #f92672; 72 | } 73 | 74 | .token.boolean, 75 | .token.number { 76 | color: #ae81ff; 77 | } 78 | 79 | .token.selector, 80 | .token.attr-name, 81 | .token.string, 82 | .token.char, 83 | .token.builtin, 84 | .token.inserted { 85 | color: #a6e22e; 86 | } 87 | 88 | .token.operator, 89 | .token.entity, 90 | .token.url, 91 | .language-css .token.string, 92 | .style .token.string, 93 | .token.variable { 94 | color: #f8f8f2; 95 | } 96 | 97 | .token.atrule, 98 | .token.attr-value, 99 | .token.function { 100 | color: #e6db74; 101 | } 102 | 103 | .token.keyword { 104 | color: #66d9ef; 105 | } 106 | 107 | .token.regex, 108 | .token.important { 109 | color: #fd971f; 110 | } 111 | 112 | .token.important, 113 | .token.bold { 114 | font-weight: bold; 115 | } 116 | .token.italic { 117 | font-style: italic; 118 | } 119 | 120 | .token.entity { 121 | cursor: help; 122 | } 123 | 124 | pre.line-numbers { 125 | position: relative; 126 | padding-left: 3.8em; 127 | counter-reset: linenumber; 128 | } 129 | 130 | pre.line-numbers > code { 131 | position: relative; 132 | } 133 | 134 | .line-numbers .line-numbers-rows { 135 | position: absolute; 136 | pointer-events: none; 137 | top: 0; 138 | font-size: 100%; 139 | left: -3.8em; 140 | width: 3em; /* works for line-numbers below 1000 lines */ 141 | letter-spacing: -1px; 142 | border-right: 1px solid #999; 143 | 144 | -webkit-user-select: none; 145 | -moz-user-select: none; 146 | -ms-user-select: none; 147 | user-select: none; 148 | 149 | } 150 | 151 | .line-numbers-rows > span { 152 | pointer-events: none; 153 | display: block; 154 | counter-increment: linenumber; 155 | } 156 | 157 | .line-numbers-rows > span:before { 158 | content: counter(linenumber); 159 | color: #999; 160 | display: block; 161 | padding-right: 0.8em; 162 | text-align: right; 163 | } 164 | pre.code-toolbar { 165 | position: relative; 166 | } 167 | 168 | pre.code-toolbar > .toolbar { 169 | position: absolute; 170 | top: .3em; 171 | right: .2em; 172 | transition: opacity 0.3s ease-in-out; 173 | opacity: 0; 174 | } 175 | 176 | pre.code-toolbar:hover > .toolbar { 177 | opacity: 1; 178 | } 179 | 180 | pre.code-toolbar > .toolbar .toolbar-item { 181 | display: inline-block; 182 | } 183 | 184 | pre.code-toolbar > .toolbar a { 185 | cursor: pointer; 186 | } 187 | 188 | pre.code-toolbar > .toolbar button { 189 | background: none; 190 | border: 0; 191 | color: inherit; 192 | font: inherit; 193 | line-height: normal; 194 | overflow: visible; 195 | padding: 0; 196 | -webkit-user-select: none; /* for button */ 197 | -moz-user-select: none; 198 | -ms-user-select: none; 199 | } 200 | 201 | pre.code-toolbar > .toolbar a, 202 | pre.code-toolbar > .toolbar button, 203 | pre.code-toolbar > .toolbar span { 204 | color: #bbb; 205 | font-size: .8em; 206 | padding: 0 .5em; 207 | background: #f5f2f0; 208 | background: rgba(224, 224, 224, 0.2); 209 | box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); 210 | border-radius: .5em; 211 | } 212 | 213 | pre.code-toolbar > .toolbar a:hover, 214 | pre.code-toolbar > .toolbar a:focus, 215 | pre.code-toolbar > .toolbar button:hover, 216 | pre.code-toolbar > .toolbar button:focus, 217 | pre.code-toolbar > .toolbar span:hover, 218 | pre.code-toolbar > .toolbar span:focus { 219 | color: inherit; 220 | text-decoration: none; 221 | } 222 | 223 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /themes/leonids-clone/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /themes/leonids-clone/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /themes/leonids-clone/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /themes/leonids-clone/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /themes/leonids-clone/static/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/images/favicon.png -------------------------------------------------------------------------------- /themes/leonids-clone/static/images/gravatar_wrapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/images/gravatar_wrapper.png -------------------------------------------------------------------------------- /themes/leonids-clone/static/images/touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekodour/gitpushblog/ef8e6351c13c417887c27bf41ae0888ff63bd1ff/themes/leonids-clone/static/images/touch-icon.png -------------------------------------------------------------------------------- /themes/leonids-clone/static/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript for gitpushblog, webpack + init stuff 3 | */ 4 | 5 | import { initCommentSystem, initPostCategoryPage, displaySignOut } from './utils'; 6 | import { firebaseService } from './services'; 7 | 8 | // only imported assets will be available inside assets directory 9 | 10 | import '../css/main.scss'; 11 | import '../images/favicon.png'; 12 | 13 | // end of file imports 14 | 15 | const blogInfo = window.blogInfo; 16 | const bc = blogInfo.bc; 17 | 18 | // init firebase and display signout if signedin 19 | if(bc.comment.isGithubAuth){ 20 | firebaseService.init(); 21 | displaySignOut(); 22 | } 23 | 24 | switch(blogInfo.pageType){ 25 | case "index": 26 | break; 27 | case "post": 28 | initCommentSystem(); 29 | break; 30 | case "category": 31 | // you can enable async loading of category posts by toggling template_cat_posts 32 | // by default this is false 33 | if(!bc.others.template_cat_posts){ 34 | initPostCategoryPage(); 35 | } 36 | break; 37 | default: 38 | break; 39 | } 40 | 41 | 42 | /* 43 | * Add your custom javascript below 44 | */ 45 | 46 | console.log('wow!'); 47 | -------------------------------------------------------------------------------- /themes/leonids-clone/static/js/services.js: -------------------------------------------------------------------------------- 1 | const bc = window.blogInfo.bc; 2 | 3 | const firebaseInit = ()=>{ 4 | let config = bc.firebaseConfig; 5 | firebase.initializeApp(config); 6 | } 7 | 8 | const githubSignIn = ()=>{ 9 | let provider = new firebase.auth.GithubAuthProvider(); 10 | // this `scope` takes private repo permissions 11 | // need a lower permission than access to private repo. 12 | // any `scope` that only enables to comment on issues? 13 | provider.addScope('repo'); 14 | return new Promise((resolve,reject)=>{ 15 | firebase.auth().signInWithPopup(provider) 16 | .then(function(result) { 17 | let token = result.credential.accessToken; 18 | resolve(token); 19 | }) 20 | .catch(function(error) { 21 | // handle this, right now it's just copy paste from docs 22 | let errorCode = error.code; 23 | }); 24 | }); 25 | } 26 | 27 | const disqusInit = ()=>{ 28 | let disqus_config = function () { 29 | this.page.url = location.href; 30 | this.page.identifier = location.href; 31 | }; 32 | (function() { 33 | var d = document, s = d.createElement('script'); 34 | s.src = `https://${bc.comment.disqus_id}.disqus.com/embed.js`; 35 | s.setAttribute('data-timestamp', +new Date()); 36 | (d.head || d.body).appendChild(s); 37 | })(); 38 | } 39 | 40 | export const firebaseService = { 41 | init: firebaseInit, 42 | signIn: githubSignIn 43 | } 44 | 45 | export const disqusService = { 46 | init: disqusInit 47 | } 48 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(env) { 2 | return require(`./webpack.${env}.js`) 3 | } 4 | -------------------------------------------------------------------------------- /webpack.dev.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 4 | const webpack = require('webpack'); 5 | const yaml = require('js-yaml'); 6 | 7 | const bc = yaml.safeLoad(fs.readFileSync(path.join('_config.yml'), 'utf8')); 8 | const THEME_DIR = path.join(__dirname,'themes',bc.meta.blog_theme) 9 | 10 | // plugin inits 11 | 12 | // to extract css out of javascript 13 | const extractCss = new ExtractTextPlugin({ 14 | filename: "[name].css" 15 | }); 16 | 17 | // to ignore the unicode table(2mb) for unicode slug 18 | const ignorePlugin = new webpack.IgnorePlugin(/unicode\/category\/So/); 19 | 20 | // end plugin inits 21 | 22 | 23 | module.exports = { 24 | devtool: 'cheap-module-source-map', 25 | 26 | // this will throw error if you're don't have prism.js alongside your main.js 27 | entry: { 28 | vendors: [path.join(THEME_DIR,'static','js','prism.js')], 29 | main: path.join(THEME_DIR,'static','js','main.js') 30 | }, 31 | 32 | output: { 33 | path: path.join(__dirname,'dev','assets'), 34 | filename: '[name].js', 35 | sourceMapFilename: '[name].map' 36 | }, 37 | 38 | module: { 39 | rules: [ 40 | { 41 | test: /\.(js|jsx)$/, 42 | use: [ 43 | {loader:'babel-loader'} 44 | ], 45 | exclude: /node_modules/ 46 | }, 47 | { 48 | test: /\.(scss|sass)$/, 49 | use: extractCss.extract({ 50 | use: [{ 51 | loader: "css-loader" 52 | }, 53 | { 54 | loader: "postcss-loader" 55 | }, 56 | { 57 | loader: "sass-loader" 58 | }], 59 | fallback: "style-loader" 60 | }) 61 | }, 62 | { 63 | test: /\.css$/, 64 | use: extractCss.extract({ 65 | use: 66 | [ 67 | {loader:'css-loader'} 68 | ], 69 | fallback: "style-loader" 70 | }) 71 | }, 72 | { 73 | test: /\.(png|jpg|gif|svg)$/, 74 | use: [ 75 | { 76 | loader:'file-loader', 77 | query: { 78 | name: "[name].[ext]", 79 | useRelativePath: false, 80 | publicPath: '', 81 | outputPath: 'img/' 82 | } 83 | } 84 | ] 85 | }, 86 | { 87 | test: /\.(woff|woff2|eot|ttf|otf)$/, 88 | use: [ 89 | { 90 | loader:'file-loader', 91 | query: { 92 | name: "[name].[ext]", 93 | useRelativePath: false, 94 | publicPath: '', 95 | outputPath: 'fonts/' 96 | } 97 | } 98 | ] 99 | } 100 | ] 101 | }, 102 | plugins: [ 103 | ignorePlugin, 104 | extractCss 105 | ] 106 | 107 | } 108 | -------------------------------------------------------------------------------- /webpack.prod.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 4 | const webpack = require('webpack'); 5 | const yaml = require('js-yaml'); 6 | 7 | const bc = yaml.safeLoad(fs.readFileSync(path.join('_config.yml'), 'utf8')); 8 | const THEME_DIR = path.join(__dirname,'themes',bc.meta.blog_theme) 9 | 10 | // plugin inits 11 | const extractCss = new ExtractTextPlugin({ 12 | filename: "[name].css" 13 | }); 14 | 15 | // to ignore the unicode table(2mb) for unicode slug 16 | const ignorePlugin = new webpack.IgnorePlugin(/unicode\/category\/So/); 17 | 18 | const uglify = new webpack.optimize.UglifyJsPlugin({ 19 | compress: { 20 | warnings: false, 21 | drop_console: false, 22 | } 23 | }); 24 | // end plugin inits 25 | 26 | module.exports = { 27 | entry: { 28 | vendors: [path.join(THEME_DIR,'static','js','prism.js')], 29 | main: path.join(THEME_DIR,'static','js','main.js') 30 | }, 31 | 32 | output: { 33 | path: path.join(__dirname, 'dist','assets'), 34 | filename: '[name].js' 35 | }, 36 | 37 | module: { 38 | rules: [ 39 | { 40 | test: /\.(js|jsx)$/, 41 | use: [ 42 | {loader:'babel-loader'} 43 | ], 44 | exclude: /node_modules/ 45 | }, 46 | { 47 | test: /\.(sass|scss)$/, 48 | use: extractCss.extract({ 49 | use: [{ 50 | loader: "css-loader", 51 | options: { minimize: true } 52 | }, 53 | { 54 | loader: "postcss-loader" 55 | }, 56 | { 57 | loader: "sass-loader", 58 | options: { minimize: true } 59 | }], 60 | // use style-loader in development 61 | fallback: "style-loader" 62 | }) 63 | }, 64 | { 65 | test: /\.css$/, 66 | use: extractCss.extract({ 67 | use: 68 | [ 69 | { 70 | loader:'css-loader', 71 | options: { minimize: true } 72 | } 73 | ], 74 | fallback: "style-loader" 75 | }) 76 | }, 77 | { 78 | test: /\.(png|jpg|gif|svg)$/, 79 | use: [ 80 | { 81 | loader:'file-loader', 82 | query: { 83 | name: "[name].[ext]", 84 | useRelativePath: false, 85 | publicPath: '', 86 | outputPath: 'img/' 87 | } 88 | } 89 | ] 90 | }, 91 | { 92 | test: /\.(woff|woff2|eot|ttf|otf)$/, 93 | use: [ 94 | { 95 | loader:'file-loader', 96 | query: { 97 | name: "[name].[ext]", 98 | useRelativePath: false, 99 | publicPath: '', 100 | outputPath: 'fonts/' 101 | } 102 | } 103 | ] 104 | } 105 | ] 106 | }, 107 | plugins: [ 108 | ignorePlugin, 109 | extractCss, 110 | uglify 111 | ] 112 | 113 | } 114 | --------------------------------------------------------------------------------