├── .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 |
--------------------------------------------------------------------------------