├── .gitattributes ├── .gitignore ├── app ├── images │ ├── favicon.ico │ ├── apple-touch-icon.png │ └── deja-vu-sans-mono.woff ├── src │ └── app.coffee ├── styl │ └── app.styl └── index.html ├── test ├── main.spec.coffee └── bootstrap.coffee ├── .editorconfig ├── LICENSE ├── package.json ├── README.md └── gulpfile.coffee /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | -------------------------------------------------------------------------------- /app/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gokmen/zar/HEAD/app/images/favicon.ico -------------------------------------------------------------------------------- /app/images/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gokmen/zar/HEAD/app/images/apple-touch-icon.png -------------------------------------------------------------------------------- /app/images/deja-vu-sans-mono.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gokmen/zar/HEAD/app/images/deja-vu-sans-mono.woff -------------------------------------------------------------------------------- /test/main.spec.coffee: -------------------------------------------------------------------------------- 1 | describe 'zar test', -> 2 | 3 | page = null 4 | 5 | before -> 6 | page = await browser.newPage() 7 | await page.goto 'http://localhost:9000' 8 | 9 | after -> 10 | await page.close() 11 | 12 | it 'should have zar in page title', -> 13 | expect(await page.title()).to.eql 'zar' 14 | 15 | it 'should have the zarlar in it', -> 16 | SELECTOR = '.zarlar > div' 17 | 18 | await page.waitFor SELECTOR 19 | -------------------------------------------------------------------------------- /test/bootstrap.coffee: -------------------------------------------------------------------------------- 1 | puppeteer = require 'puppeteer' 2 | { expect } = require 'chai' 3 | _ = require 'lodash' 4 | globalVariables = _.pick global, ['browser', 'expect'] 5 | 6 | opts = 7 | headless: yes 8 | timeout: 10000 9 | 10 | 11 | before -> 12 | 13 | global.expect = expect 14 | global.browser = await puppeteer.launch opts 15 | 16 | 17 | after -> 18 | 19 | global.browser.close() 20 | 21 | global.browser = globalVariables.browser 22 | global.expect = globalVariables.expect 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /app/src/app.coffee: -------------------------------------------------------------------------------- 1 | kd = require 'kd.js' 2 | 3 | class Zar extends kd.View 4 | 5 | @N = ['⚀', '⚁', '⚂', '⚃', '⚄', '⚅'] 6 | @getRandom = -> 7 | @N[Math.floor Math.random() * 6] 8 | 9 | constructor: (options = {}, data = Zar.getRandom()) -> 10 | options.cssClass = 'zar' 11 | super options, data 12 | 13 | pistachio: -> '{{#(0)}}' 14 | 15 | roll: -> 16 | @setClass 'rolling' 17 | @setData Zar.getRandom() 18 | kd.utils.wait 500, @lazyBound 'unsetClass', 'rolling' 19 | 20 | class Zarlar extends kd.View 21 | 22 | constructor: (options = {}, data) -> 23 | options.cssClass = 'zarlar' 24 | super options, data 25 | 26 | @zarlar = [ 27 | (@addSubView new Zar) 28 | (@addSubView new Zar) 29 | ] 30 | 31 | click: -> 32 | @zarlar.forEach (zar) -> zar.roll() 33 | 34 | do -> 35 | 36 | zarlar = new Zarlar 37 | zarlar.appendToDomBody() 38 | -------------------------------------------------------------------------------- /app/styl/app.styl: -------------------------------------------------------------------------------- 1 | @font-face 2 | font-family 'DejaVu' 3 | src url('/images/deja-vu-sans-mono.woff') format('woff') 4 | 5 | body 6 | font-family 'DejaVu', sans-serif 7 | width 100% 8 | height 100% 9 | position fixed 10 | overflow hidden 11 | 12 | @keyframes pulse 13 | 0% 14 | opacity 0 15 | 100% 16 | opacity 1 17 | 18 | .zar 19 | color white 20 | font-size 50vw 21 | text-align center 22 | 23 | width 50vw 24 | float left 25 | 26 | cursor default 27 | -webkit-touch-callout none 28 | -webkit-user-select none 29 | -khtml-user-select none 30 | -moz-user-select none 31 | -ms-user-select none 32 | user-select none 33 | 34 | span 35 | position absolute 36 | top 50% 37 | left 50% 38 | transform translate(-50%, -55%) 39 | 40 | &.rolling 41 | animation pulse .6s 42 | 43 | .zarlar 44 | background black 45 | text-selection none 46 | height 100vh -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | zar 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Gokmen Goksel 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zar", 3 | "version": "0.0.1", 4 | "description": "zar: yet another kd.js project", 5 | "license": "MIT", 6 | "private": true, 7 | "scripts": { 8 | "start": "gulp", 9 | "build": "gulp build", 10 | "clean": "gulp clean", 11 | "test": "gulp test", 12 | "production": "gulp production", 13 | "test:watch": "gulp test-watch" 14 | }, 15 | "keywords": [ 16 | "zar", 17 | "kd", 18 | "kd.js" 19 | ], 20 | "author": "Gokmen Goksel ", 21 | "devDependencies": { 22 | "browser-sync": "^2.23.6", 23 | "browserify": "^16.1.0", 24 | "chai": "^4.1.2", 25 | "coffeeify": "^3.0.1", 26 | "coffeescript": "^2.2.1", 27 | "connect-history-api-fallback": "^1.5.0", 28 | "ecstatic": "^3.2.0", 29 | "gulp": "^3.9.1", 30 | "gulp-coffee": "^3.0.2", 31 | "gulp-minify-css": "^1.2.4", 32 | "gulp-spawn-mocha": "^5.0.1", 33 | "gulp-streamify": "^1.0.2", 34 | "gulp-stylus": "^2.7.0", 35 | "gulp-uglify-es": "^1.0.1", 36 | "gulp-util": "^3.0.8", 37 | "istanbul": "^0.4.5", 38 | "lodash": "^4.17.5", 39 | "mocha": "^5.0.1", 40 | "puppeteer": "^1.1.0", 41 | "rimraf": "^2.6.2", 42 | "vinyl-source-stream": "^2.0.0" 43 | }, 44 | "dependencies": { 45 | "kd.js": "^1.2.4" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zar 2 | 3 | A simple dice application for web and mobile platforms. Simply visit https://zar.now.sh or https://dice.now.sh and tap on the screen to roll the dices. If you want you can create a desktop shortcut for the Zar for both iOS and Android and you can use it as an application. 4 | 5 | ## Getting Started 6 | 7 | After cloning the repo, cd into `zar` directory and do; 8 | 9 | ``` 10 | $ npm install 11 | $ npm start 12 | ``` 13 | 14 | This will open your browser with `localhost:9000` and you should see the `zar` project alive \o/ 15 | 16 | ## Production 17 | 18 | By default while developing there is no minify or uglify process happening but for production environments to reduce the file sizes we need to tell builder (gulp) to generate output for production; 19 | 20 | ``` 21 | $ npm run production 22 | ``` 23 | 24 | This will build everything for production and then run tests. You can use the `./dist` folder to deploy your app, all the required files are in that folder, production ready. 25 | 26 | ## Tests 27 | 28 | You can run tests simply by calling; 29 | 30 | ``` 31 | $ npm test 32 | ``` 33 | 34 | This will start testing for every `.coffee` files under `./test` directory. Where you can see an example test in `main.spec.coffee`. In the same folder there is another file called `bootstrap.coffee` which is responsible for booting up Puppeteer for tests. 35 | 36 | If you want to keep tests running whenever the bundle or a test spec changed; 37 | 38 | ``` 39 | $ npm run test:watch 40 | ``` 41 | 42 | ## License 43 | 44 | MIT 2018 Gokmen Goksel 45 | -------------------------------------------------------------------------------- /gulpfile.coffee: -------------------------------------------------------------------------------- 1 | gulp = require 'gulp' 2 | gutil = require 'gulp-util' 3 | mocha = require 'gulp-spawn-mocha' 4 | stylus = require 'gulp-stylus' 5 | uglify = require('gulp-uglify-es').default 6 | streamify = require 'gulp-streamify' 7 | CSSmin = require 'gulp-minify-css' 8 | 9 | rimraf = require 'rimraf' 10 | source = require 'vinyl-source-stream' 11 | coffeeify = require 'coffeeify' 12 | browserify = require 'browserify' 13 | 14 | production = process.env.NODE_ENV is 'production' 15 | browserSync = require('browser-sync').create() 16 | 17 | # to make browser-sync catch all the routes and redirect them to index.html, 18 | # kind of SPA mode. 19 | # see: 20 | # https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-60410751 21 | historyFallback = require 'connect-history-api-fallback' 22 | 23 | openApp = yes 24 | globalBundler = null 25 | 26 | paths = 27 | scripts : 28 | watch : './app/src/*.coffee' 29 | source : './app/src/app.coffee' 30 | destination : './dist/js/' 31 | filename : './app.js' 32 | vendor : './vendor.js' 33 | styles : 34 | source : './app/styl/app.styl' 35 | watch : './app/styl/*.styl' 36 | destination : './dist/css/' 37 | entryPoint : 38 | source : './app/index.html' 39 | watch : './app/index.html' 40 | destination : './dist/' 41 | images : 42 | source : './app/images/*' 43 | destination : './dist/images/' 44 | test : 45 | app : './dist/**/*' 46 | cases : './test/*.coffee' 47 | 48 | 49 | handleError = (err) -> 50 | err = err.message if err.message? 51 | gutil.log err 52 | gutil.beep() 53 | this.emit 'end' 54 | 55 | 56 | getBrowserifiedBundler = -> 57 | 58 | return globalBundler if globalBundler 59 | 60 | globalBundler = browserify 61 | cache : {} 62 | packageCache : {} 63 | fullPaths : no 64 | entries : [ paths.scripts.source ] 65 | extensions : [ '.coffee' ] 66 | transform : [ 'coffeeify' ] 67 | debug : !production 68 | 69 | globalBundler.external 'kd.js' 70 | 71 | return globalBundler 72 | 73 | 74 | gulp.task 'compile-vendors', -> 75 | 76 | vendorBundler = browserify 77 | cache : {} 78 | packageCache : {} 79 | fullPaths : no 80 | require : 'kd.js' 81 | debug : !production 82 | 83 | bundle = vendorBundler.bundle() 84 | .on 'error', handleError 85 | .pipe source paths.scripts.vendor 86 | 87 | bundle.pipe streamify uglify() if production 88 | bundle 89 | .pipe gulp.dest paths.scripts.destination 90 | .pipe browserSync.reload stream: yes 91 | 92 | 93 | gulp.task 'compile-scripts', -> 94 | 95 | bundle = getBrowserifiedBundler().bundle() 96 | .on 'error', handleError 97 | .pipe source paths.scripts.filename 98 | 99 | bundle.pipe streamify uglify() if production 100 | bundle 101 | .pipe gulp.dest paths.scripts.destination 102 | .pipe browserSync.reload stream: yes 103 | 104 | 105 | gulp.task 'watch', -> 106 | 107 | gulp.watch paths.styles.watch, [ 'styles' ] 108 | gulp.watch paths.scripts.watch, [ 'compile-scripts' ] 109 | 110 | 111 | gulp.task 'styles', -> 112 | 113 | styles = gulp 114 | .src paths.styles.source 115 | .pipe stylus set: ['include css'] 116 | .on 'error', handleError 117 | 118 | styles = styles.pipe CSSmin() if production 119 | 120 | styles 121 | .pipe gulp.dest paths.styles.destination 122 | .pipe browserSync.reload stream: yes 123 | 124 | 125 | gulp.task 'server', [ 'compile' ], -> 126 | 127 | gulp.start [ 'run-server' ] 128 | 129 | 130 | gulp.task 'run-server', -> 131 | 132 | browserSync.init 133 | notify : no 134 | open : openApp 135 | port : 9000 136 | server : 137 | baseDir : './dist' 138 | middleware : [ historyFallback() ] 139 | 140 | 141 | gulp.task 'entry-point', -> 142 | 143 | gulp 144 | .src paths.entryPoint.source 145 | .pipe gulp.dest paths.entryPoint.destination 146 | 147 | 148 | gulp.task 'images', -> 149 | 150 | gulp 151 | .src paths.images.source 152 | .pipe gulp.dest paths.images.destination 153 | 154 | 155 | gulp.task 'export-kd', -> 156 | 157 | # Just copy kd.css to dist 158 | gulp 159 | .src './node_modules/kd.js/dist/kd.css' 160 | .pipe gulp.dest './dist/css/' 161 | 162 | 163 | gulp.task 'clean', (cb) -> rimraf './dist', cb 164 | 165 | gulp.task 'enable-test-watch', [ 'default' ], -> 166 | 167 | gulp.watch paths.test.app, [ 'single-test' ] 168 | gulp.watch paths.test.cases, [ 'single-test' ] 169 | 170 | gulp.start 'single-test' 171 | 172 | gulp.task 'enable-prod', -> production = yes 173 | 174 | gulp.task 'disable-open', -> openApp = no 175 | 176 | gulp.task 'prod-build', [ 'enable-prod', 'serve-only', 'test' ] 177 | 178 | gulp.task 'production', [ 'prod-build' ], -> 179 | 180 | gutil.log 'Building for production is completed, 181 | you can now deploy ./dist folder' 182 | 183 | gulp.task 'test', [ 'disable-open', 'serve-only' ], (done) -> 184 | 185 | gulp 186 | .src ['./test/*.coffee'], read: no 187 | .pipe mocha 188 | reporter: 'list' 189 | require: 'coffeescript/register' 190 | 191 | .on 'end', -> 192 | browserSync.exit() 193 | 194 | .once 'error', -> 195 | @emit 'end' 196 | 197 | gulp.task 'single-test', -> 198 | 199 | gulp 200 | .src ['./test/*.coffee'], read: no 201 | .pipe mocha 202 | reporter: 'list' 203 | require: 'coffeescript/register' 204 | 205 | .once 'error', -> 206 | @emit 'end' 207 | 208 | 209 | gulp.task 'test-watch', [ 'enable-test-watch' ] 210 | 211 | gulp.task 'compile', [ 'compile-vendors', 'compile-scripts' ] 212 | 213 | gulp.task 'build', [ 214 | 'compile', 'styles', 'entry-point', 'export-kd', 'images' 215 | ] 216 | 217 | gulp.task 'serve-only', [ 218 | 'build', 'server' 219 | ] 220 | 221 | gulp.task 'default', [ 222 | 'build', 'watch', 'server' 223 | ] 224 | --------------------------------------------------------------------------------