├── .babelrc ├── .github └── workflows │ └── semgrep.yml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── package.json ├── screenshots ├── tv-roll-mid.jpg └── tv-roll-top.jpg ├── src ├── inferno │ ├── components │ │ └── welcome-component.js │ ├── index-template.html │ ├── index.js │ └── styles │ │ └── stylesheet.css ├── mincss │ ├── img │ │ ├── asia.png │ │ ├── beach.png │ │ ├── bees.png │ │ ├── coffee.png │ │ ├── documentaries.png │ │ ├── forest.png │ │ ├── logo.svg │ │ ├── seats.jpg │ │ ├── shoes.png │ │ └── spiderman.jpg │ ├── index-template.html │ ├── index.js │ └── styles │ │ └── styles.less ├── photo │ ├── components │ │ ├── blob-component.js │ │ ├── card-component.js │ │ ├── footer-component.js │ │ ├── header-component.js │ │ ├── main-component.js │ │ └── top-header-component.js │ ├── favicon.ico │ ├── img │ │ └── logo.svg │ ├── index-template.html │ ├── index.js │ ├── styles │ │ └── styles.less │ └── tvmaze.js └── purecss │ ├── index-template.html │ ├── index.js │ └── styles │ └── styles.css └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015" ], 3 | "plugins": [["inferno", {"imports": true}]] 4 | } 5 | -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: {} 3 | push: 4 | branches: 5 | - main 6 | - master 7 | paths: 8 | - .github/workflows/semgrep.yml 9 | schedule: 10 | - cron: '0 0 * * 0' 11 | name: Semgrep 12 | jobs: 13 | semgrep: 14 | name: Scan 15 | runs-on: ubuntu-20.04 16 | env: 17 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 18 | container: 19 | image: returntocorp/semgrep 20 | steps: 21 | - uses: actions/checkout@v3 22 | - run: semgrep ci 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | static 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Travis build config 2 | sudo: false 3 | language: node_js 4 | node_js: 5 | - "5.10.1" 6 | 7 | cache: 8 | directories: 9 | - node_modules 10 | 11 | install: 12 | - npm install 13 | 14 | script: 15 | - npm run test 16 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hirako2000@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Hirako 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/86dcd0601595468db66ed2be1c7f23de)](https://app.codacy.com/app/hirako2000/polypack?utm_source=github.com&utm_medium=referral&utm_content=hirako2000/polypack&utm_campaign=Badge_Grade_Dashboard) 2 | [![Build Status](https://travis-ci.org/hirako2000/polypack.svg?branch=master)](https://travis-ci.org/hirako2000/polypack) 3 | [![Dependency Status](https://david-dm.org/hirako2000/polypack.svg?style=flat)](https://david-dm.org/hirako2000/polypack) 4 | [![devDependency Status](https://david-dm.org/hirako2000/polypack/dev-status.svg)](https://david-dm.org/hirako2000/polypack#info=devDependencies) 5 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/hirako2000/polypack/blob/master/LICENSE) 6 | 7 | # polypack 8 | 9 | Polypack is a boilerplate configuration to build the most lightweight front end assets for webapp or static pages. 10 | 11 | The motivation behind this project started from observation that most if not all boilerplates are either bloated with heavyweight libs, or incomplete in order to develop and ship production applications. 12 | 13 | ### Features 14 | 15 | - Ready to use build and bundling system with [webpack](https://webpack.github.io/) 16 | - Most lightweight libraries for [performance](https://medium.com/reloading/javascript-start-up-performance-69200f43b201) 17 | - Web application, react-like skeleton 18 | - State store 19 | - Static web page setup 20 | - Support for either or both [{less}](http://lesscss.org/)/[Sass](http://sass-lang.com/) 21 | - Support for various web fonts formats 22 | - [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) for rapid development 23 | - ES6/7 24 | - Linting 25 | - Production build with minified, concat and gzipped content 26 | 27 | ### Roadmap 28 | 29 | - [x] Base bundler with webpack 3 & Babel 30 | - [x] Multi SPA bundler config 31 | - [x] Hot Module Reload 32 | - [x] Production build 33 | - [x] Cross environment variables 34 | - [x] Gzip 35 | - [x] Less support 36 | - [x] Sass support 37 | - [x] Fonts support 38 | - [x] Inferno JS skeleton 39 | - [x] Redux skeleton 40 | - [x] PureCSS skeleton 41 | - [x] mincss skeleton 42 | - [x] Inferno sample webapp 43 | - [x] Linter 44 | - [ ] Jest 45 | 46 | ### TV program roll webapp example with Inferno/redux & mincss 47 | 48 | HBO look & feel with [Mincss](http://mincss.com/) 49 | 50 | [Live Demo](http://polypack-tv.surge.sh/) 51 | 52 | ![top](https://raw.githubusercontent.com/hirako2000/polypack/master/screenshots/tv-roll-top.jpg) 53 | ![mid](https://raw.githubusercontent.com/hirako2000/polypack/master/screenshots/tv-roll-mid.jpg) 54 | 55 | #### Size 56 | 57 | ``` 58 | Asset Size Chunks Chunk Names 59 | bcff9e9b7b53122acb52df67cd5f4d4f.svg 1.99 kB [emitted] 60 | photo.js 14.6 kB 0 [emitted] photo 61 | photo.vendor.js 114 kB 4 [emitted] photo.vendor 62 | photo.css 3.97 kB 0 [emitted] photo 63 | photo.vendor.css 1.95 kB 4 [emitted] photo.vendor 64 | photo.html 398 bytes [emitted] 65 | ``` 66 | #### Size (gzipped) 67 | ``` 68 | bcff9e9b7b53122acb52df67cd5f4d4f.svg.gz 901 bytes [emitted] 69 | photo.js.gz 2.88 kB [emitted] 70 | photo.vendor.js.gz 27.9 kB [emitted] 71 | photo.css.gz 1.32 kB [emitted] 72 | photo.vendor.css.gz 850 bytes [emitted] 73 | photo.html 398 bytes [emitted] 74 | ``` 75 | ### Potato shop 76 | Landing page with Inferno & [Basscss](http://basscss.com/) 77 | 78 | [Live Demo](https://eager-potatoes.surge.sh/) | [Source](https://github.com/hirako2000/polypack-potatoes) 79 | 80 | ![](https://raw.githubusercontent.com/hirako2000/polypack-potatoes/master/screenshots/potato-top.png) 81 | 82 | #### Size 83 | 84 | ``` 85 | Asset Size Chunks Chunk Names 86 | potatoes.css.map 89 bytes 0 [emitted] potatoes 87 | potatoes.js 21.9 kB 0 [emitted] potatoes 88 | potatoes.vendor.js 51.4 kB 1 [emitted] potatoes.vendor 89 | potatoes.css 4.65 kB 0 [emitted] potatoes 90 | potatoes.vendor.css 9.89 kB 1 [emitted] potatoes.vendor 91 | potatoes.vendor.css.map 96 bytes 1 [emitted] potatoes.vendor 92 | index.html 418 bytes [emitted] 93 | ``` 94 | #### Size (gzipped) 95 | ``` 96 | Asset Size Chunks Chunk Names 97 | potatoes.js.gz 3.09 kB [emitted] 98 | potatoes.css.gz 1.98 kB [emitted] 99 | potatoes.vendor.css.gz 2.31 kB [emitted] 100 | potatoes.vendor.js.gz 15.4 kB [emitted] 101 | index.html 418 bytes [emitted] 102 | ``` 103 | 104 | ### Folder structure 105 | ``` 106 | . 107 | ├── src # Applications source code 108 | │ ├── inferno # Inferno app 109 | │ │ ├── components # Components 110 | │ │ ├── styles # Styles 111 | │ | ├── index-template.html # HTML template 112 | │ | └── index.js # Entry point 113 | │ ├── mincss # Mincss landing page 114 | │ │ ├── img # images 115 | │ │ ├── styles # Styles 116 | │ | ├── index-template.html # HTML template 117 | │ | └── index.js # Entry point 118 | │ ├── photo # Inferno app for TV roll example 119 | │ │ ├── components # Components 120 | │ │ ├── img # Images 121 | │ │ ├── styles # Styles 122 | │ | ├── index-template.html # HTML template 123 | │ | └── index.js # Entry point 124 | │ └── purecss # Purecss landing page 125 | │ ├── img # images 126 | │ ├── styles # Styles 127 | │ ├── index-template.html # HTML template 128 | │ └── index.js # Entry point 129 | ├── static # Output of prod assets 130 | └── webpack.config.js # Webpack config for both dev and prod builds 131 | ``` 132 | ### HOWTO 133 | Simply fork, or download the zip content of this repo. 134 | #### Prerequisite 135 | - Node.js 136 | 137 | #### Run 138 | ```bash 139 | npm install # installs deps 140 | ``` 141 | 142 | ```bash 143 | npm start # starts the app in dev mode 144 | ``` 145 | ```bash 146 | npm run build # builds app for production 147 | ``` 148 | #### Browse 149 | There are multiple web apps built by default 150 | - [http://localhost:3000/mincss.html](http://localhost:3000/mincss.html) - mincss starter 151 | - [http://localhost:3000/purecss.html](http://localhost:3000/purecss.html) - purecss starter 152 | - [http://localhost:3000/inferno.html](http://localhost:3000/inferno.html) - inferno/redux starter 153 | - [http://localhost:3000/photo.html](http://localhost:3000/photo.html) - the tv roll exampe (inferno/redux fetching TVmaze schedules) 154 | 155 | 156 | ### Contributing 157 | PR are welcome 158 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polypack", 3 | "version": "1.0.1", 4 | "description": "Webpack skeleton", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack-dev-server", 8 | "prod": "cross-env NODE_ENV=production webpack-dev-server --env.prod=true", 9 | "build": "cross-env NODE_ENV=production webpack --env.prod=true", 10 | "test": "xo ./src/**/*.js" 11 | }, 12 | "keywords": [ 13 | "webpack" 14 | ], 15 | "author": "hirako2000", 16 | "repository": "https://github.com/hirako2000/polypack", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "babel-core": "^6.26.3", 20 | "babel-loader": "^7.1.5", 21 | "babel-plugin-inferno": "^3.1.0", 22 | "babel-preset-es2015": "^6.22.0", 23 | "compression-webpack-plugin": "^0.4.0", 24 | "cross-env": "^5.2.0", 25 | "css-loader": "^0.28.4", 26 | "eslint-config-xo": "^0.18.2", 27 | "eslint-config-xo-inferno": "^0.11.1", 28 | "eslint-plugin-inferno": "^6.10.4", 29 | "extract-text-webpack-plugin": "^2.1.2", 30 | "file-loader": "^0.11.2", 31 | "html-loader": "^0.4.4", 32 | "html-webpack-plugin": "^2.29.0", 33 | "less": "^2.7.2", 34 | "less-loader": "^4.1.0", 35 | "style-loader": "^0.18.2", 36 | "url-loader": "^0.5.9", 37 | "webpack": "^3.0.0", 38 | "webpack-dev-server": "^2.5.0", 39 | "xo": "^0.18.2" 40 | }, 41 | "dependencies": { 42 | "basscss": "^8.0.4", 43 | "fecha": "^2.3.3", 44 | "furtive": "^2.4.0", 45 | "inferno": "^3.3.1", 46 | "inferno-component": "^3.3.1", 47 | "inferno-redux": "^3.3.1", 48 | "inferno-router": "^3.3.1", 49 | "inferno-shared": "^3.1.1", 50 | "lodash": "^4.17.10", 51 | "mincss-modules": "^2.0.0", 52 | "netflixroulette-js": "0.0.1", 53 | "purecss": "^1.0.0", 54 | "redux": "^3.6.0" 55 | }, 56 | "xo": { 57 | "extends": [ 58 | "xo/esnext", 59 | "xo-inferno/space" 60 | ], 61 | "env": "browser", 62 | "semicolon": false, 63 | "space": 2, 64 | "unicorn/filename-case": 0, 65 | "import/no-extraneous-dependencies": 0 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /screenshots/tv-roll-mid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/screenshots/tv-roll-mid.jpg -------------------------------------------------------------------------------- /screenshots/tv-roll-top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/screenshots/tv-roll-top.jpg -------------------------------------------------------------------------------- /src/inferno/components/welcome-component.js: -------------------------------------------------------------------------------- 1 | import Component from 'inferno-component' 2 | 3 | export default class WelcomeComponent extends Component { 4 | constructor(props) { 5 | super(props) 6 | this.state = { 7 | name: 'Inferno' 8 | } 9 | } 10 | render() { 11 | return ( 12 |
13 |

{this.props.message} - {this.state.name}

14 |
15 | ) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/inferno/index-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /src/inferno/index.js: -------------------------------------------------------------------------------- 1 | import Inferno from 'inferno' 2 | import * as furtive from 'furtive/css/furtive.css' 3 | import * as styles from './styles/stylesheet.css' 4 | import WelcomeComponent from './components/welcome-component' 5 | 6 | const message = 'Furtive' 7 | Inferno.render( 8 |
9 |
10 | 11 |
, 12 | document.getElementById('app') 13 | ) 14 | 15 | export {furtive, styles} 16 | -------------------------------------------------------------------------------- /src/inferno/styles/stylesheet.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin: 2%; 3 | } 4 | 5 | .header { 6 | max-height: 60px; 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | .logo { 12 | height: 100px; 13 | } 14 | -------------------------------------------------------------------------------- /src/mincss/img/asia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/asia.png -------------------------------------------------------------------------------- /src/mincss/img/beach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/beach.png -------------------------------------------------------------------------------- /src/mincss/img/bees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/bees.png -------------------------------------------------------------------------------- /src/mincss/img/coffee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/coffee.png -------------------------------------------------------------------------------- /src/mincss/img/documentaries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/documentaries.png -------------------------------------------------------------------------------- /src/mincss/img/forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/forest.png -------------------------------------------------------------------------------- /src/mincss/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Shape 4 | Some Logo 5 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/mincss/img/seats.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/seats.jpg -------------------------------------------------------------------------------- /src/mincss/img/shoes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/shoes.png -------------------------------------------------------------------------------- /src/mincss/img/spiderman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/mincss/img/spiderman.jpg -------------------------------------------------------------------------------- /src/mincss/index-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 17 |
18 | 29 | 30 | 31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | Spider Man | Premiere sunday at 10:30 PM 39 |
40 |
41 | He is coming back 42 |
43 |
44 | Peter Parker (Tobey Maguire) and M.J. (Kirsten Dunst) seem to finally be on the right track in their complicated relationship, but trouble looms for the superhero and his lover 45 |
46 | 47 | Find out more 48 | 49 |
50 |
51 |
52 | 53 | 54 | 55 |
56 |
57 |
58 | 59 |
60 | Spider Man | Premiere sunday at 10:30 PM 61 |
62 |
63 | He is coming back 64 |
65 |
66 | Peter Parker (Tobey Maguire) and M.J. (Kirsten Dunst) seem to finally be on the right track in their complicated relationship, but trouble looms for the superhero and his lover 67 |
68 | 69 | Find out more 70 | 71 |
72 |
73 |
74 |
75 | 76 |
77 | Spider Man | Premiere sunday at 10:30 PM 78 |
79 |
80 | He is coming back 81 |
82 |
83 | Peter Parker (Tobey Maguire) and M.J. (Kirsten Dunst) seem to finally be on the right track in their complicated relationship, but trouble looms for the superhero and his lover 84 |
85 | 86 | Find out more 87 | 88 |
89 |
90 |
91 | 92 | 93 |
94 |
95 |
96 | 97 |
98 | Spider Man | Premiere sunday at 10:30 PM 99 |
100 |
101 | He is coming back 102 |
103 |
104 | Peter Parker (Tobey Maguire) and M.J. (Kirsten Dunst) seem to finally be on the right track in their complicated relationship, but trouble looms for the superhero and his lover 105 |
106 | 107 | Find out more 108 | 109 |
110 |
111 |
112 |
113 | 114 |
115 | Spider Man | Premiere sunday at 10:30 PM 116 |
117 |
118 | He is coming back 119 |
120 |
121 | Peter Parker (Tobey Maguire) and M.J. (Kirsten Dunst) seem to finally be on the right track in their complicated relationship, but trouble looms for the superhero and his lover 122 |
123 | 124 | Find out more 125 | 126 |
127 |
128 |
129 |
130 | 131 |
132 | Spider Man | Premiere sunday at 10:30 PM 133 |
134 |
135 | He is coming back 136 |
137 |
138 | Peter Parker (Tobey Maguire) and M.J. (Kirsten Dunst) seem to finally be on the right track in their complicated relationship, but trouble looms for the superhero and his lover 139 |
140 | 141 | Find out more 142 | 143 |
144 |
145 |
146 |
147 | 148 | 149 | 150 | 175 | 176 |
177 | 178 | 179 | -------------------------------------------------------------------------------- /src/mincss/index.js: -------------------------------------------------------------------------------- 1 | import * as buttons from 'mincss-modules/less/buttons.less' 2 | import * as grid from 'mincss-modules/less/grid.less' 3 | import * as icons from 'mincss-modules/less/icons.less' 4 | import * as navbar from 'mincss-modules/less/navbar.less' 5 | import * as tables from 'mincss-modules/less/tables.less' 6 | import * as forms from 'mincss-modules/less/forms.less' 7 | import * as styles from './styles/styles.less' 8 | import * as logo from './img/logo.svg' 9 | 10 | export {buttons, grid, icons, navbar, tables, forms, styles, logo} 11 | -------------------------------------------------------------------------------- /src/mincss/styles/styles.less: -------------------------------------------------------------------------------- 1 | @whiteTrans72: rgba(255,255,255,.72); 2 | @whiteTrans48: rgba(255,255,255,.48); 3 | @mainBackground: #141414; 4 | @darkerBackground: #0a0a0a; 5 | @containerMargin: 3.2rem; 6 | @gutterSize: @containerMargin / 4; 7 | @thatYellow: #caad2d; 8 | @thinBorder: 1px solid #1f1f1f; 9 | 10 | body { 11 | margin: 0; 12 | font-family: 'Montserrat', sans-serif; 13 | background-color: @mainBackground; 14 | color: @whiteTrans72; 15 | } 16 | 17 | .row-gutter { 18 | margin-left: -@gutterSize; 19 | margin-right: -@gutterSize; 20 | } 21 | 22 | .my25em { 23 | margin-top: 2.5em; 24 | margin-bottom: 2.5em; 25 | } 26 | 27 | .p16 { 28 | padding: 1.6em; 29 | } 30 | 31 | .py18 { 32 | padding-top: 1.8em; 33 | padding-bottom: 1.8em; 34 | } 35 | 36 | .py16 { 37 | padding-top: 1.6em; 38 | padding-bottom: 1.6em; 39 | } 40 | 41 | .margb24 { 42 | margin-bottom: 24px; 43 | } 44 | 45 | .gutter-content { 46 | padding-left: @gutterSize; 47 | padding-right: @gutterSize; 48 | } 49 | 50 | .footer-container { 51 | color: @whiteTrans48; 52 | border-top: @thinBorder; 53 | padding-left: @containerMargin; 54 | padding-right: @containerMargin; 55 | background-color: @darkerBackground; 56 | } 57 | 58 | .large-footer { 59 | padding-top: 15px; 60 | font-size: 14px; 61 | } 62 | 63 | .very-footer { 64 | font-size: 12px; 65 | padding-top: 15px; 66 | padding-bottom: 15px; 67 | border-top: @thinBorder; 68 | background-color: @darkerBackground; 69 | } 70 | 71 | .nav-top { 72 | outline: none; 73 | height: 28px; 74 | line-height: 28px; 75 | border-bottom: @thinBorder; 76 | background-color: @darkerBackground; 77 | } 78 | 79 | .right-menu { 80 | float: right; 81 | margin-right: 3%; 82 | } 83 | 84 | a { 85 | font-size: 11px; 86 | -webkit-transition: color .15s cubic-bezier(.35,0,.25,1); 87 | transition: color .15s cubic-bezier(.35,0,.25,1); 88 | text-decoration: none; 89 | color: @whiteTrans48; 90 | margin-left: 12px; 91 | } 92 | 93 | a:active, a:hover { 94 | outline: 0; 95 | color: #fff; 96 | } 97 | 98 | .container { 99 | margin-right: @containerMargin; 100 | margin-left: @containerMargin; 101 | padding-bottom: 30px; 102 | } 103 | 104 | .nav-main a { 105 | color: @whiteTrans72; 106 | font-size: 12px; 107 | letter-spacing: 1px; 108 | } 109 | 110 | .nav-main a:active, .nav-main a:hover { 111 | padding-bottom: 1.8em; 112 | outline: 0; 113 | color: #fff; 114 | right: 100%; 115 | border-style: solid; 116 | border-width: 0px 0px 3px 0px; 117 | border-bottom-color: #caad2d; 118 | -webkit-transition: all .3s cubic-bezier(.35,0,.25,1); 119 | transition: all .3s cubic-bezier(.35,0,.25,1); 120 | } 121 | 122 | .logo { 123 | display: inline-flex;; 124 | width: 65px; 125 | height: 28px; 126 | vertical-align: middle; 127 | margin: 0 auto; 128 | border-width: 0px; 129 | background: url(../img/logo.svg)50% 50% no-repeat; 130 | background-size: 100% auto; 131 | } 132 | 133 | .front-image { 134 | display: flex; 135 | width: 100%; 136 | } 137 | 138 | .background-text { 139 | background: #1f1f1f; 140 | } 141 | 142 | 143 | .movie-title { 144 | font-size: 12px; 145 | line-height: 16px; 146 | color: rgba(255,255,255,.48); 147 | text-transform: uppercase; 148 | } 149 | 150 | .movie-description { 151 | margin: 0 0 24px; 152 | font-size: 12px; 153 | line-height: 20px; 154 | color: rgba(255,255,255,.72); 155 | } 156 | 157 | .movie-tagline { 158 | font-size: 24px; 159 | line-height: 24px; 160 | color: #fff; 161 | margin: 0 0 24px; 162 | } 163 | 164 | .that-yellow { 165 | margin: 0 0 12px; 166 | color: @thatYellow; 167 | } 168 | 169 | .find-out { 170 | letter-spacing: 1px; 171 | font-size: 12px; 172 | text-transform: uppercase; 173 | margin: 0 0 12px; 174 | color: #a99026; 175 | } 176 | 177 | .find-out:hover { 178 | color: @thatYellow; 179 | } 180 | 181 | .border-left { 182 | border-left: 1px solid; 183 | } 184 | 185 | .margin-bottom-end { 186 | margin-bottom: 40px; 187 | } 188 | -------------------------------------------------------------------------------- /src/photo/components/blob-component.js: -------------------------------------------------------------------------------- 1 | import Inferno from 'inferno' 2 | import Component from 'inferno-component' 3 | import {connect} from 'inferno-redux' 4 | import orderBy from 'lodash/orderBy' 5 | import fetch from '../tvmaze' 6 | import CardComponent from './card-component' 7 | 8 | class BlobComponent extends Component { 9 | 10 | componentWillMount() { 11 | const thiz = this 12 | fetch(0) 13 | .then(response => { 14 | const sortedShows = orderBy(response, [o => { 15 | return o.show.weight && o.show.rating.average > 0 ? o.show.weight : 0 16 | }, o => { 17 | return o.show.rating.average > 0 ? o.show.rating.average : 0 18 | }], ['desc', 'desc']) 19 | 20 | thiz.setState({ 21 | shows: sortedShows 22 | }) 23 | 24 | thiz.props.store.dispatch({ 25 | type: 'SHOWS', 26 | name: sortedShows 27 | }) 28 | }).catch(err => { 29 | console.log('Error: ' + err) 30 | }) 31 | } 32 | 33 | render() { 34 | if (!this.props.shows) { 35 | return (
Loading...
) 36 | } 37 | 38 | return ( 39 |
40 |
41 |
42 | 43 |
44 |
45 |
46 |
47 | {this.props.shows[0].show.name} | Season {this.props.shows[0].season} Ep {this.props.shows[0].number} 48 |
49 |
50 | {this.props.shows[0].name} 51 |
52 |
53 | {this.props.shows[0].summary ? this.props.shows[0].summary.replace(/(<([^>]+)>)/ig, '') : this.props.shows[0].show.summary.replace(/(<([^>]+)>)/ig, '') } 54 |
55 | 56 | Find out more 57 | 58 |
59 |
60 |
61 |
62 |
63 | 64 |
65 |
66 | 67 |
68 |
69 | 70 |
71 |
72 | 73 |
74 |
75 | 76 |
77 |
78 | 79 |
80 |
81 |
82 |
83 | 84 |
85 |
86 | 87 |
88 |
89 | 90 |
91 |
92 |
) 93 | } 94 | } 95 | 96 | const mapStateToProps = state => ({ 97 | shows: state.shows 98 | }) 99 | 100 | export default connect(mapStateToProps)(BlobComponent) 101 | -------------------------------------------------------------------------------- /src/photo/components/card-component.js: -------------------------------------------------------------------------------- 1 | import Inferno from 'inferno' 2 | import Component from 'inferno-component' 3 | 4 | class CardComponent extends Component { 5 | componentDidMount() { 6 | } 7 | 8 | prettyText(show) { 9 | let summary = show.summary ? show.summary : show.show.summary 10 | summary = summary.replace(/(<([^>]+)>)/ig, '') 11 | if (summary.length > 200) { 12 | summary = summary.substring(0, 200) + '...' 13 | } 14 | return summary 15 | } 16 | 17 | render() { 18 | const show = this.props.show 19 | const genres = [] 20 | if (show.show.genres && show.show.genres.length > 0) { 21 | for (let i = 0; i < show.show.genres.length; i++) { 22 | genres.push({show.show.genres[i]}) 23 | if (i < show.show.genres.length - 1) { 24 | genres.push( | ) 25 | } 26 | } 27 | } 28 | const imageCount = this.props.imageCount 29 | let imageStyles = 'fit-image' 30 | imageStyles = imageCount === 1 ? imageStyles += ' front-image' : imageCount === 2 ? imageStyles += ' two-image' : imageStyles += ' three-image' 31 | return ( 32 |
33 | 34 |
35 | {show.show.name} - Season {show.season} Ep {show.number} 36 | 37 | {show.airtime} 38 | 39 |
40 | {genres} 41 |
42 |
43 | 44 |
45 | {show.name} 46 |
47 |
48 | { this.prettyText(show) } 49 |
50 |
51 | 52 | { show.show.network.name } 53 | 54 | 55 | Rating: { show.show.rating.average } 56 | 57 |
58 | 59 | Find out more 60 | 61 |
62 | ) 63 | } 64 | } 65 | 66 | export default CardComponent 67 | -------------------------------------------------------------------------------- /src/photo/components/footer-component.js: -------------------------------------------------------------------------------- 1 | import Inferno from 'inferno' 2 | import Component from 'inferno-component' 3 | 4 | class FooterComponent extends Component { 5 | render() { 6 | return ( 7 |
8 |
9 |
10 |
11 |
12 | Source on Github 13 |
14 |
15 |
16 |
17 |
18 | ©2017 Some Rights Reserved. Schedules retreived from TVmaze. This website may contain mature content. 19 |
20 |
21 | ) 22 | } 23 | } 24 | 25 | export default FooterComponent 26 | -------------------------------------------------------------------------------- /src/photo/components/header-component.js: -------------------------------------------------------------------------------- 1 | import Inferno from 'inferno' 2 | import Component from 'inferno-component' 3 | import {connect} from 'inferno-redux' 4 | import orderBy from 'lodash/orderBy' 5 | import fetch from '../tvmaze' 6 | 7 | const DAYS = ['SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY'] 8 | 9 | class HeaderComponent extends Component { 10 | constructor(props) { 11 | super(props) 12 | this.handleClick = this.handleClick.bind(this) 13 | } 14 | 15 | componentDidMount() { 16 | } 17 | 18 | componentWillMount() { 19 | const date = new Date() 20 | this.setState({ 21 | today: date.getDay(), 22 | day: date.getDay() 23 | }) 24 | } 25 | 26 | handleClick(day) { 27 | this.setState({day}) 28 | this.fetchShows() 29 | } 30 | 31 | fetchShows() { 32 | const thiz = this 33 | let shift = 0 34 | if (this.state.day !== this.state.today) { 35 | if (this.state.day - this.state.today < 0) { 36 | shift = 7 + (this.state.day - this.state.today) 37 | } else { 38 | shift = this.state.day - this.state.today 39 | } 40 | } 41 | thiz.props.store.dispatch({ 42 | type: 'SHOWS', 43 | name: null 44 | }) 45 | fetch(shift) 46 | .then(response => { 47 | const sortedShows = orderBy(response, [o => { 48 | return o.show.weight && o.show.rating.average > 0 ? o.show.weight : 0 49 | }, o => { 50 | return o.show.rating.average > 0 ? o.show.rating.average : 0 51 | }], ['desc', 'desc']) 52 | 53 | thiz.props.store.dispatch({ 54 | type: 'SHOWS', 55 | name: sortedShows 56 | }) 57 | }).catch(err => { 58 | console.log('Error: ' + err) 59 | }) 60 | } 61 | 62 | render() { 63 | const days = [] 64 | for (let i = 0; i < DAYS.length; i++) { 65 | const thisDay = DAYS[i] 66 | const thisDayNum = i 67 | days.push( 68 | 76 | {thisDay} 77 | 78 | ) 79 | } 80 | 81 | return ( 82 | 88 | ) 89 | } 90 | } 91 | 92 | const mapStateToProps = state => ({ 93 | shows: state.shows 94 | }) 95 | 96 | export default connect(mapStateToProps)(HeaderComponent) 97 | -------------------------------------------------------------------------------- /src/photo/components/main-component.js: -------------------------------------------------------------------------------- 1 | import Inferno from 'inferno' 2 | import Component from 'inferno-component' 3 | import FooterComponent from './footer-component' 4 | import TopHeaderComponent from './top-header-component' 5 | import BlobComponent from './blob-component' 6 | import HeaderComponent from './header-component' 7 | 8 | class MainComponent extends Component { 9 | componentDidMount() { 10 | } 11 | 12 | render() { 13 | return ( 14 |
15 | 16 |
17 | 18 | 19 |
20 | 21 |
) 22 | } 23 | } 24 | 25 | export default MainComponent 26 | -------------------------------------------------------------------------------- /src/photo/components/top-header-component.js: -------------------------------------------------------------------------------- 1 | import Component from 'inferno-component' 2 | import Inferno from 'inferno' 3 | 4 | class TopHeaderComponent extends Component { 5 | render() { 6 | return ( 7 |
13 | ) 14 | } 15 | } 16 | 17 | export default TopHeaderComponent 18 | -------------------------------------------------------------------------------- /src/photo/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirako2000/polypack/1cf9d86c5b194e5cf72b55f95f3eb7bcefca790a/src/photo/favicon.ico -------------------------------------------------------------------------------- /src/photo/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Shape 4 | Some Logo 5 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/photo/index-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /src/photo/index.js: -------------------------------------------------------------------------------- 1 | import Inferno from 'inferno' 2 | import {Provider} from 'inferno-redux' 3 | import {createStore} from 'redux' 4 | import * as buttons from 'mincss-modules/less/buttons.less' 5 | import * as grid from 'mincss-modules/less/grid.less' 6 | import * as icons from 'mincss-modules/less/icons.less' 7 | import * as navbar from 'mincss-modules/less/navbar.less' 8 | import * as tables from 'mincss-modules/less/tables.less' 9 | import * as forms from 'mincss-modules/less/forms.less' 10 | import * as styles from './styles/styles.less' 11 | import * as logo from './img/logo.svg' 12 | import MainComponent from './components/main-component' 13 | 14 | const store = createStore((state, action) => { 15 | switch (action.type) { 16 | case 'SHOWS': 17 | return { 18 | shows: action.name 19 | } 20 | default: 21 | return { 22 | shows: null 23 | } 24 | } 25 | }) 26 | 27 | Inferno.render( 28 | 29 | 30 | , document.getElementById('app') 31 | ) 32 | 33 | export {buttons, grid, icons, navbar, tables, forms, styles, logo} 34 | -------------------------------------------------------------------------------- /src/photo/styles/styles.less: -------------------------------------------------------------------------------- 1 | @whiteTrans72: rgba(255,255,255,.72); 2 | @whiteTrans48: rgba(255,255,255,.48); 3 | @mainBackground: #141414; 4 | @darkerBackground: #0a0a0a; 5 | @containerMargin: 3.2rem; 6 | @gutterSize: @containerMargin / 4; 7 | @thatYellow: #caad2d; 8 | @thinBorder: 1px solid #1f1f1f; 9 | @objectFit: cover; 10 | 11 | body { 12 | margin: 0; 13 | font-family: 'Montserrat', sans-serif; 14 | background-color: @mainBackground; 15 | color: @whiteTrans72; 16 | } 17 | 18 | .float-right { 19 | float: right; 20 | } 21 | 22 | .social { 23 | height: 3em; 24 | fill: @whiteTrans48; 25 | } 26 | 27 | .social:hover { 28 | height: 3em; 29 | fill: @whiteTrans72; 30 | } 31 | 32 | .row-gutter { 33 | margin-left: -@gutterSize; 34 | margin-right: -@gutterSize; 35 | } 36 | 37 | .my25em { 38 | margin-top: 2.5em; 39 | margin-bottom: 2.5em; 40 | } 41 | 42 | .p16 { 43 | padding: 1.6em; 44 | } 45 | 46 | .py18 { 47 | padding-top: 1.8em; 48 | padding-bottom: 1.8em; 49 | } 50 | 51 | .py16 { 52 | padding-top: 1.6em; 53 | padding-bottom: 1.6em; 54 | } 55 | 56 | .pt14 { 57 | padding-top: 1.4em; 58 | } 59 | 60 | .pb8 { 61 | padding-bottom: 0.8em; 62 | } 63 | 64 | .margb24 { 65 | margin-bottom: 24px; 66 | } 67 | 68 | .gutter-content { 69 | padding-left: @gutterSize; 70 | padding-right: @gutterSize; 71 | } 72 | 73 | .footer-container { 74 | color: @whiteTrans48; 75 | border-top: @thinBorder; 76 | padding-left: @containerMargin; 77 | padding-right: @containerMargin; 78 | background-color: @darkerBackground; 79 | } 80 | 81 | .large-footer { 82 | padding-top: 15px; 83 | font-size: 14px; 84 | } 85 | 86 | .very-footer { 87 | font-size: 0.6em; 88 | padding-top: 1em; 89 | padding-bottom: 1em; 90 | background-color: @darkerBackground; 91 | } 92 | 93 | .very-footer a { 94 | font-size: 1em; 95 | text-decoration: none; 96 | color: rgba(255, 255, 255, 0.68); 97 | margin-left: 0; 98 | } 99 | 100 | .row a { 101 | font-size: 1em; 102 | } 103 | 104 | .nav-top { 105 | outline: none; 106 | height: 28px; 107 | line-height: 28px; 108 | border-bottom: @thinBorder; 109 | background-color: @darkerBackground; 110 | } 111 | 112 | .right-menu { 113 | float: right; 114 | margin-right: 3%; 115 | } 116 | 117 | a { 118 | font-size: 11px; 119 | -webkit-transition: color .15s cubic-bezier(.35,0,.25,1); 120 | transition: color .15s cubic-bezier(.35,0,.25,1); 121 | text-decoration: none; 122 | color: @whiteTrans48; 123 | margin-left: 12px; 124 | } 125 | 126 | a:active, a:hover { 127 | outline: 0; 128 | color: #fff; 129 | } 130 | 131 | .container { 132 | margin-right: @containerMargin; 133 | margin-left: @containerMargin; 134 | padding-bottom: 30px; 135 | } 136 | 137 | .nav-main a { 138 | color: @whiteTrans72; 139 | font-size: 12px; 140 | letter-spacing: 1px; 141 | } 142 | 143 | .nav-main a:active, .nav-main a:hover { 144 | outline: 0; 145 | color: #fff; 146 | right: 100%; 147 | } 148 | 149 | .underline { 150 | padding-bottom: 1.8em; 151 | outline: 0; 152 | color: #fff; 153 | right: 100%; 154 | border-style: solid; 155 | border-width: 0 0 3px; 156 | border-bottom-color: #caad2d; 157 | -webkit-transition: all .3s cubic-bezier(.35,0,.25,1); 158 | transition: all .3s cubic-bezier(.35,0,.25,1); 159 | } 160 | 161 | .logo { 162 | display: inline-flex;; 163 | width: 65px; 164 | height: 28px; 165 | vertical-align: middle; 166 | margin: 0 auto; 167 | border-width: 0px; 168 | background: url(../img/logo.svg)50% 50% no-repeat; 169 | background-size: 100% auto; 170 | } 171 | 172 | .fit-image { 173 | display: flex; 174 | width: 100%; 175 | } 176 | 177 | @media (max-width: 870px) { 178 | .front-image { 179 | object-fit: @objectFit; 180 | min-height: 450px; 181 | max-height: 450px; 182 | } 183 | 184 | .two-image { 185 | object-fit: @objectFit; 186 | min-height: 350px; 187 | max-height: 350px; 188 | } 189 | 190 | .three-image { 191 | object-fit: @objectFit; 192 | max-height: 350px; 193 | max-height: 350px; 194 | } 195 | } 196 | 197 | @media (min-width: 870px) { 198 | .front-image { 199 | object-fit: @objectFit; 200 | min-height: 450px; 201 | max-height: 450px; 202 | } 203 | 204 | .two-image { 205 | object-fit: @objectFit; 206 | min-height: 300px; 207 | max-height: 300px; 208 | } 209 | 210 | .three-image { 211 | object-fit: @objectFit; 212 | min-height: 200px; 213 | max-height: 200px; 214 | } 215 | } 216 | 217 | .background-text { 218 | background: #1f1f1f; 219 | } 220 | 221 | .genres { 222 | font-size: 0.6rem; 223 | color: @whiteTrans48; 224 | text-transform: uppercase; 225 | } 226 | 227 | .airtime { 228 | float: right; 229 | } 230 | 231 | .movie-title { 232 | font-size: 12px; 233 | line-height: 16px; 234 | color: @whiteTrans48; 235 | text-transform: uppercase; 236 | } 237 | 238 | .movie-description { 239 | text-align: justify; 240 | margin: 0 0 24px; 241 | font-size: 12px; 242 | line-height: 20px; 243 | color: @whiteTrans72; 244 | } 245 | 246 | .movie-tagline { 247 | font-size: 24px; 248 | line-height: 24px; 249 | color: #fff; 250 | margin: 0 0 24px; 251 | } 252 | 253 | .that-yellow { 254 | margin: 0 0 12px; 255 | color: @thatYellow; 256 | } 257 | 258 | .find-out { 259 | letter-spacing: 1px; 260 | font-size: 12px; 261 | text-transform: uppercase; 262 | margin: 0 0 12px; 263 | color: #a99026; 264 | } 265 | 266 | .find-out:hover { 267 | color: @thatYellow; 268 | } 269 | 270 | .border-left { 271 | border-left: 1px solid; 272 | } 273 | 274 | .margin-bottom-end { 275 | margin-bottom: 40px; 276 | } 277 | 278 | .loader, 279 | .loader:before, 280 | .loader:after { 281 | background: #ffffff; 282 | -webkit-animation: load1 1s infinite ease-in-out; 283 | animation: load1 1s infinite ease-in-out; 284 | width: 1em; 285 | height: 4em; 286 | } 287 | 288 | .loader { 289 | height: 600px; 290 | color: #ffffff; 291 | text-indent: -9999em; 292 | margin: 88px auto; 293 | position: relative; 294 | font-size: 11px; 295 | -webkit-transform: translateZ(0); 296 | -ms-transform: translateZ(0); 297 | transform: translateZ(0); 298 | -webkit-animation-delay: -0.16s; 299 | animation-delay: -0.16s; 300 | } 301 | .loader:before, 302 | .loader:after { 303 | position: absolute; 304 | top: 0; 305 | content: ''; 306 | } 307 | .loader:before { 308 | left: -1.5em; 309 | -webkit-animation-delay: -0.32s; 310 | animation-delay: -0.32s; 311 | } 312 | .loader:after { 313 | left: 1.5em; 314 | } 315 | @-webkit-keyframes load1 { 316 | 0%, 317 | 80%, 318 | 100% { 319 | box-shadow: 0 0; 320 | height: 4em; 321 | } 322 | 40% { 323 | box-shadow: 0 -2em; 324 | height: 5em; 325 | } 326 | } 327 | @keyframes load1 { 328 | 0%, 329 | 80%, 330 | 100% { 331 | box-shadow: 0 0; 332 | height: 4em; 333 | } 334 | 40% { 335 | box-shadow: 0 -2em; 336 | height: 5em; 337 | } 338 | } 339 | 340 | /* Fad in */ 341 | .fade-in { 342 | margin-top: 25px; 343 | font-size: 21px; 344 | -webkit-animation: fadein 2s; /* Safari, Chrome and Opera > 12.1 */ 345 | -ms-animation: fadein 2s; /* Internet Explorer */ 346 | animation: fadein 2s; 347 | } 348 | 349 | @keyframes fadein { 350 | from { opacity: 0; } 351 | to { opacity: 1; } 352 | } 353 | 354 | /* Safari, Chrome and Opera > 12.1 */ 355 | @-webkit-keyframes fadein { 356 | from { opacity: 0; } 357 | to { opacity: 1; } 358 | } 359 | 360 | /* Internet Explorer */ 361 | @-ms-keyframes fadein { 362 | from { opacity: 0; } 363 | to { opacity: 1; } 364 | } 365 | -------------------------------------------------------------------------------- /src/photo/tvmaze.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import fecha from 'fecha' 4 | 5 | const date = new Date() 6 | date.setDate(date.getDate() - 0) 7 | const API_URL = 'http://api.tvmaze.com/schedule?country=US&date=' 8 | 9 | const fetch = dayShift => new Promise((resolve, reject) => { 10 | const date = new Date() 11 | dayShift = dayShift ? dayShift : 0 12 | date.setDate(date.getDate() + dayShift) 13 | const formattedDate = fecha.format(date, 'YYYY-MM-DD') 14 | const urlWithDate = API_URL + formattedDate 15 | const httpReq = new XMLHttpRequest() 16 | httpReq.open('GET', urlWithDate.replace(/\s/ig, '%20'), true) 17 | httpReq.onreadystatechange = function () { 18 | if (httpReq.readyState !== 4) { 19 | return 20 | } 21 | if (httpReq.status !== 200) { 22 | reject(new Error('Unexpected HTTP status code: ' + httpReq.status)) 23 | } 24 | resolve(JSON.parse(httpReq.responseText)) 25 | } 26 | httpReq.send() 27 | }) 28 | 29 | export default fetch 30 | -------------------------------------------------------------------------------- /src/purecss/index-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |

PureCSS

10 |
11 | A Pure Button 12 | 13 | A Primary Button 14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | Peyto Lake 22 |
23 |
24 | Train 25 |
26 |
27 | T-Shirt Store 28 |
29 |
30 | Mountain 31 |
32 | 33 |
34 | Miami 35 |
36 |
37 | BCE Place, Toronto 38 |
39 |
40 | Banff 41 |
42 |
43 | Boston North Point Park 44 |
45 |
46 | 47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
#MakeModelYear
1HondaAccord2009
2ToyotaCamry2012
3HyundaiElantra2010
4FordFocus2008
89 |
90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /src/purecss/index.js: -------------------------------------------------------------------------------- 1 | import * as base from 'purecss/build/base.css' 2 | import * as buttons from 'purecss/build/buttons.css' 3 | import * as tables from 'purecss/build/tables.css' 4 | import * as menus from 'purecss/build/menus.css' 5 | import * as grids from 'purecss/build/grids.css' 6 | import * as styles from './styles/styles.css' 7 | 8 | export {base, buttons, tables, menus, grids, styles} 9 | -------------------------------------------------------------------------------- /src/purecss/styles/styles.css: -------------------------------------------------------------------------------- 1 | .header { 2 | text-align: center; 3 | } 4 | 5 | .relaxed { 6 | padding: 20px; 7 | } 8 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const CompressionPlugin = require("compression-webpack-plugin") 4 | const ExtractTextPlugin = require("extract-text-webpack-plugin") 5 | const HtmlWebpackPlugin = require('html-webpack-plugin') 6 | 7 | const sourcePath = path.join(__dirname, './src') 8 | 9 | module.exports = function (env) { 10 | const nodeEnv = env && env.prod ? 'production' : 'development' 11 | const isProd = nodeEnv === 'production' 12 | 13 | const plugins = [ 14 | new webpack.optimize.CommonsChunkPlugin({ 15 | names: ['inferno.vendor'], 16 | chunks: ['inferno'], 17 | minChunks: function (module) { 18 | return isExternal(module) 19 | } 20 | }), 21 | new webpack.optimize.CommonsChunkPlugin({ 22 | name: 'purecss.vendor', 23 | chunks: ['purecss'], 24 | minChunks: function (module) { 25 | return isExternal(module) 26 | } 27 | }), 28 | new webpack.optimize.CommonsChunkPlugin({ 29 | name: 'mincss.vendor', 30 | chunks: ['mincss'], 31 | minChunks: function (module) { 32 | return isExternal(module) 33 | } 34 | }), 35 | new webpack.optimize.CommonsChunkPlugin({ 36 | name: 'photo.vendor', 37 | chunks: ['photo'], 38 | minChunks: function (module) { 39 | return isExternal(module) 40 | } 41 | }), 42 | new webpack.DefinePlugin({ 43 | 'process.env': {NODE_ENV: JSON.stringify(nodeEnv)} 44 | }), 45 | new webpack.NamedModulesPlugin(), 46 | new HtmlWebpackPlugin({ 47 | filename: 'inferno.html', 48 | title: 'Inferno', 49 | template: 'inferno/index-template.html', 50 | chunks: ['inferno.vendor', 'inferno'] 51 | }), 52 | new HtmlWebpackPlugin({ 53 | filename: 'purecss.html', 54 | title: 'PureCSS', 55 | template: 'purecss/index-template.html', 56 | chunks: ['purecss.vendor', 'purecss'] 57 | }), 58 | new HtmlWebpackPlugin({ 59 | filename: 'mincss.html', 60 | title: 'MINCSS', 61 | template: 'mincss/index-template.html', 62 | chunks: ['mincss.vendor', 'mincss'] 63 | }), 64 | new HtmlWebpackPlugin({ 65 | filename: 'photo.html', 66 | title: 'Photo', 67 | template: 'photo/index-template.html', 68 | chunks: ['photo.vendor', 'photo'] 69 | }) 70 | ] 71 | 72 | if (isProd) { 73 | plugins.push( 74 | new webpack.LoaderOptionsPlugin({ 75 | minimize: true, 76 | debug: false 77 | }), 78 | new webpack.optimize.UglifyJsPlugin({ 79 | compress: { 80 | warnings: false 81 | }, 82 | output: { 83 | comments: false 84 | }, 85 | sourceMap: true 86 | }), 87 | new CompressionPlugin({ 88 | asset: '[path].gz[query]', 89 | algorithm: 'gzip', 90 | test: /\.js$|\.css$|\.html$|\.eot$|\.svg$|\.ttf$|\.woff$/, 91 | threshold: 1024, 92 | minRatio: 0.8 93 | }), 94 | new ExtractTextPlugin('[name].css'), 95 | new webpack.optimize.ModuleConcatenationPlugin() 96 | ) 97 | } else { 98 | plugins.push( 99 | new webpack.HotModuleReplacementPlugin() 100 | ) 101 | } 102 | 103 | return { 104 | devtool: isProd ? 'source-map' : 'eval', 105 | context: sourcePath, 106 | entry: { 107 | inferno: './inferno/index.js', 108 | purecss: './purecss/index.js', 109 | mincss: './mincss/index.js', 110 | photo: './photo/index.js' 111 | }, 112 | output: { 113 | path: __dirname + '/static', 114 | filename: '[name].js' 115 | }, 116 | module: { 117 | rules: [ 118 | { 119 | test: /\.html$/, 120 | use: { 121 | loader: 'html-loader', 122 | query: { 123 | name: '[name].[ext]' 124 | } 125 | } 126 | }, 127 | { 128 | test: /\.less$/, 129 | use: isProd ? lessExtractTextLoader() : lessNonExtractTextLoader() 130 | }, 131 | { 132 | test: /\.css$/, 133 | use: isProd ? extractTextLoader() : nonExtractTextLoader() 134 | }, 135 | { 136 | test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, 137 | loader: isProd ? 'file-loader?limit=10000&mimetype=application/font-woff' : 'url-loader?limit=10000&mimetype=application/font-woff' 138 | }, 139 | { 140 | test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 141 | loader: isProd ? 'file-loader' : 'url-loader' 142 | }, 143 | { 144 | test: /\.(jpg|jpeg|png)$/, 145 | loader: isProd ? 'file-loader' : 'url-loader' 146 | }, 147 | { 148 | test: /\.(js|jsx)$/, 149 | use: [ 150 | 'babel-loader' 151 | ] 152 | } 153 | ] 154 | }, 155 | resolve: { 156 | extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'], 157 | modules: [ 158 | path.resolve(__dirname, 'node_modules'), 159 | sourcePath 160 | ] 161 | }, 162 | 163 | plugins, 164 | 165 | performance: isProd && { 166 | maxAssetSize: 100000, 167 | maxEntrypointSize: 100000, 168 | hints: 'warning' 169 | }, 170 | 171 | stats: { 172 | colors: { 173 | green: '\u001b[32m' 174 | } 175 | }, 176 | 177 | devServer: { 178 | contentBase: './src', 179 | historyApiFallback: true, 180 | port: 3000, 181 | compress: isProd, 182 | inline: !isProd, 183 | hot: !isProd, 184 | stats: { 185 | assets: true, 186 | children: false, 187 | chunks: false, 188 | hash: false, 189 | modules: false, 190 | publicPath: false, 191 | timings: true, 192 | version: false, 193 | warnings: true, 194 | colors: { 195 | green: '\u001b[32m' 196 | } 197 | } 198 | } 199 | } 200 | } 201 | 202 | function isExternal(module) { 203 | const userRequest = module.userRequest 204 | 205 | if (typeof userRequest !== 'string') { 206 | return false 207 | } 208 | 209 | return userRequest.indexOf('bower_components') >= 0 || 210 | userRequest.indexOf('node_modules') >= 0 || 211 | userRequest.indexOf('libraries') >= 0 212 | } 213 | 214 | function nonExtractTextLoader() { 215 | return [ 216 | 'style-loader', 217 | 'css-loader?sourceMap' 218 | ] 219 | } 220 | 221 | function lessNonExtractTextLoader() { 222 | return [ 223 | 'style-loader', 224 | 'css-loader?sourceMap', 225 | 'less-loader?sourceMap' 226 | ] 227 | } 228 | 229 | function extractTextLoader() { 230 | return ExtractTextPlugin.extract({ 231 | fallback: 'style-loader', use: 'css-loader' 232 | }) 233 | } 234 | 235 | function lessExtractTextLoader() { 236 | return ExtractTextPlugin.extract({ 237 | fallback: 'style-loader', use: 'css-loader!less-loader' 238 | }) 239 | } 240 | --------------------------------------------------------------------------------