From 7eb02f07dc5eda1894a66e1cb05396279cfb3ee5 Mon Sep 17 00:00:00 2001 From: marlon-erler Date: Sun, 30 Aug 2026 16:15:14 +0200 Subject: [PATCH] implement pinch to zoom --- 1.vim | 435 +- dist/index.css | 6 +- dist/index.js | 38 +- dist/sw.js | 2 +- node_modules/component-clone/.npmignore | 1 + node_modules/component-clone/History.md | 28 + node_modules/component-clone/Makefile | 9 + node_modules/component-clone/Readme.md | 27 + node_modules/component-clone/component.json | 15 + node_modules/component-clone/index.js | 57 + node_modules/component-clone/package.json | 26 + node_modules/component-clone/test/clone.js | 80 + node_modules/component-closest/.npmignore | 59 + node_modules/component-closest/History.md | 28 + node_modules/component-closest/Makefile | 5 + node_modules/component-closest/README.md | 44 + node_modules/component-closest/component.json | 14 + node_modules/component-closest/index.js | 36 + node_modules/component-closest/package.json | 23 + .../component-closest/test/index.html | 45 + node_modules/component-delegate/.npmignore | 2 + node_modules/component-delegate/History.md | 34 + node_modules/component-delegate/Makefile | 11 + node_modules/component-delegate/Readme.md | 39 + .../component-delegate/component.json | 19 + node_modules/component-delegate/index.js | 51 + node_modules/component-delegate/package.json | 28 + .../component-delegate/test/index.html | 55 + node_modules/component-emitter/LICENSE | 24 + node_modules/component-emitter/Readme.md | 74 + node_modules/component-emitter/index.js | 175 + node_modules/component-emitter/package.json | 28 + node_modules/component-event/.npmignore | 2 + node_modules/component-event/History.md | 28 + node_modules/component-event/Makefile | 11 + node_modules/component-event/Readme.md | 39 + node_modules/component-event/component.json | 14 + node_modules/component-event/index.js | 35 + node_modules/component-event/package.json | 19 + node_modules/component-event/test/index.html | 33 + node_modules/component-events/.npmignore | 2 + node_modules/component-events/History.md | 53 + node_modules/component-events/Makefile | 11 + node_modules/component-events/Readme.md | 112 + node_modules/component-events/component.json | 20 + .../component-events/examples/delegation.html | 45 + .../component-events/examples/events.html | 26 + .../component-events/examples/method.html | 26 + node_modules/component-events/index.js | 185 + node_modules/component-events/package.json | 21 + .../component-matches-selector/.npmignore | 2 + .../component-matches-selector/History.md | 42 + .../component-matches-selector/Makefile | 11 + .../component-matches-selector/Readme.md | 20 + .../component-matches-selector/component.json | 20 + .../component-matches-selector/index.js | 51 + .../component-matches-selector/package.json | 22 + .../test/index.html | 17 + .../component-matches-selector/test/mocha.css | 199 + .../component-matches-selector/test/mocha.js | 4699 +++++++++++++++ .../component-matches-selector/test/tests.js | 35 + node_modules/component-query/.npmignore | 2 + node_modules/component-query/History.md | 18 + node_modules/component-query/Makefile | 11 + node_modules/component-query/Readme.md | 42 + node_modules/component-query/component.json | 21 + node_modules/component-query/example.html | 19 + node_modules/component-query/index.js | 21 + node_modules/component-query/package.json | 24 + node_modules/component-raf/.npmignore | 2 + node_modules/component-raf/History.md | 26 + node_modules/component-raf/Makefile | 11 + node_modules/component-raf/Readme.md | 46 + node_modules/component-raf/component.json | 16 + node_modules/component-raf/example.html | 43 + node_modules/component-raf/index.js | 34 + node_modules/component-raf/package.json | 21 + node_modules/component-tap-event/LICENSE | 22 + node_modules/component-tap-event/README.md | 63 + node_modules/component-tap-event/index.js | 87 + node_modules/component-tap-event/package.json | 38 + node_modules/component-tween/.npmignore | 2 + node_modules/component-tween/History.md | 27 + node_modules/component-tween/Makefile | 16 + node_modules/component-tween/Readme.md | 78 + node_modules/component-tween/component.json | 25 + .../component-tween/examples/array.html | 48 + .../component-tween/examples/ball.html | 64 + .../component-tween/examples/circle.html | 45 + .../component-tween/examples/dom.html | 41 + .../component-tween/examples/interactive.html | 62 + .../component-tween/examples/rect.html | 43 + node_modules/component-tween/index.js | 178 + .../node_modules/component-emitter/History.md | 63 + .../node_modules/component-emitter/LICENSE | 24 + .../node_modules/component-emitter/Readme.md | 74 + .../node_modules/component-emitter/index.js | 161 + .../component-emitter/package.json | 24 + node_modules/component-tween/package.json | 32 + node_modules/component-type/.npmignore | 3 + node_modules/component-type/Makefile | 14 + node_modules/component-type/Readme.md | 37 + node_modules/component-type/component.json | 13 + node_modules/component-type/index.js | 34 + node_modules/component-type/package.json | 16 + node_modules/component-type/test/index.html | 17 + node_modules/component-type/test/mocha.css | 231 + node_modules/component-type/test/mocha.js | 5340 +++++++++++++++++ node_modules/component-type/test/tests.js | 72 + node_modules/ease-component/.npmignore | 2 + node_modules/ease-component/Makefile | 14 + node_modules/ease-component/Readme.md | 106 + node_modules/ease-component/component.json | 15 + node_modules/ease-component/example.html | 46 + node_modules/ease-component/index.js | 170 + node_modules/ease-component/package.json | 13 + node_modules/global-object/README.md | 68 + node_modules/global-object/global-object.js | 1 + node_modules/global-object/package.json | 22 + node_modules/has-translate3d/.npmignore | 2 + node_modules/has-translate3d/History.md | 16 + node_modules/has-translate3d/Makefile | 11 + node_modules/has-translate3d/Readme.md | 17 + node_modules/has-translate3d/component.json | 15 + node_modules/has-translate3d/index.js | 24 + node_modules/has-translate3d/package.json | 15 + node_modules/prop-detect/.travis.yml | 6 + node_modules/prop-detect/Makefile | 7 + node_modules/prop-detect/Readme.md | 29 + node_modules/prop-detect/index.js | 56 + node_modules/prop-detect/karma.conf.js | 73 + node_modules/prop-detect/package.json | 44 + node_modules/prop-detect/test/test.js | 31 + node_modules/touchaction-property/.npmignore | 2 + node_modules/touchaction-property/History.md | 6 + node_modules/touchaction-property/Makefile | 11 + node_modules/touchaction-property/Readme.md | 19 + .../touchaction-property/component.json | 21 + node_modules/touchaction-property/index.js | 20 + .../touchaction-property/package.json | 25 + .../touchaction-property/test/index.html | 10 + node_modules/transform-property/.npmignore | 2 + node_modules/transform-property/History.md | 5 + node_modules/transform-property/Makefile | 11 + node_modules/transform-property/Readme.md | 17 + .../transform-property/component.json | 13 + node_modules/transform-property/index.js | 19 + node_modules/transform-property/package.json | 9 + node_modules/transition-property/Makefile | 7 + node_modules/transition-property/Readme.md | 12 + node_modules/transition-property/index.js | 20 + .../transition-property/karma.conf.js | 73 + node_modules/transition-property/package.json | 32 + node_modules/transition-property/test/test.js | 9 + src/Model/Utility/utility.ts | 30 + src/View/ChatPages/boardKanbanPage.tsx | 6 +- src/View/ChatPages/boardStatusGridPage.tsx | 6 +- src/View/ChatPages/taskPage.css | 7 +- src/ViewModel/Global/coreViewModel.ts | 2 +- src/index.tsx | 1 + 160 files changed, 15806 insertions(+), 61 deletions(-) create mode 100644 node_modules/component-clone/.npmignore create mode 100644 node_modules/component-clone/History.md create mode 100644 node_modules/component-clone/Makefile create mode 100644 node_modules/component-clone/Readme.md create mode 100644 node_modules/component-clone/component.json create mode 100644 node_modules/component-clone/index.js create mode 100644 node_modules/component-clone/package.json create mode 100644 node_modules/component-clone/test/clone.js create mode 100644 node_modules/component-closest/.npmignore create mode 100644 node_modules/component-closest/History.md create mode 100644 node_modules/component-closest/Makefile create mode 100644 node_modules/component-closest/README.md create mode 100644 node_modules/component-closest/component.json create mode 100644 node_modules/component-closest/index.js create mode 100644 node_modules/component-closest/package.json create mode 100644 node_modules/component-closest/test/index.html create mode 100644 node_modules/component-delegate/.npmignore create mode 100644 node_modules/component-delegate/History.md create mode 100644 node_modules/component-delegate/Makefile create mode 100644 node_modules/component-delegate/Readme.md create mode 100644 node_modules/component-delegate/component.json create mode 100644 node_modules/component-delegate/index.js create mode 100644 node_modules/component-delegate/package.json create mode 100644 node_modules/component-delegate/test/index.html create mode 100644 node_modules/component-emitter/LICENSE create mode 100644 node_modules/component-emitter/Readme.md create mode 100644 node_modules/component-emitter/index.js create mode 100644 node_modules/component-emitter/package.json create mode 100644 node_modules/component-event/.npmignore create mode 100644 node_modules/component-event/History.md create mode 100644 node_modules/component-event/Makefile create mode 100644 node_modules/component-event/Readme.md create mode 100644 node_modules/component-event/component.json create mode 100644 node_modules/component-event/index.js create mode 100644 node_modules/component-event/package.json create mode 100644 node_modules/component-event/test/index.html create mode 100644 node_modules/component-events/.npmignore create mode 100644 node_modules/component-events/History.md create mode 100644 node_modules/component-events/Makefile create mode 100644 node_modules/component-events/Readme.md create mode 100644 node_modules/component-events/component.json create mode 100644 node_modules/component-events/examples/delegation.html create mode 100644 node_modules/component-events/examples/events.html create mode 100644 node_modules/component-events/examples/method.html create mode 100644 node_modules/component-events/index.js create mode 100644 node_modules/component-events/package.json create mode 100644 node_modules/component-matches-selector/.npmignore create mode 100644 node_modules/component-matches-selector/History.md create mode 100644 node_modules/component-matches-selector/Makefile create mode 100644 node_modules/component-matches-selector/Readme.md create mode 100644 node_modules/component-matches-selector/component.json create mode 100644 node_modules/component-matches-selector/index.js create mode 100644 node_modules/component-matches-selector/package.json create mode 100644 node_modules/component-matches-selector/test/index.html create mode 100644 node_modules/component-matches-selector/test/mocha.css create mode 100644 node_modules/component-matches-selector/test/mocha.js create mode 100644 node_modules/component-matches-selector/test/tests.js create mode 100644 node_modules/component-query/.npmignore create mode 100644 node_modules/component-query/History.md create mode 100644 node_modules/component-query/Makefile create mode 100644 node_modules/component-query/Readme.md create mode 100644 node_modules/component-query/component.json create mode 100644 node_modules/component-query/example.html create mode 100644 node_modules/component-query/index.js create mode 100644 node_modules/component-query/package.json create mode 100644 node_modules/component-raf/.npmignore create mode 100644 node_modules/component-raf/History.md create mode 100644 node_modules/component-raf/Makefile create mode 100644 node_modules/component-raf/Readme.md create mode 100644 node_modules/component-raf/component.json create mode 100644 node_modules/component-raf/example.html create mode 100644 node_modules/component-raf/index.js create mode 100644 node_modules/component-raf/package.json create mode 100644 node_modules/component-tap-event/LICENSE create mode 100644 node_modules/component-tap-event/README.md create mode 100644 node_modules/component-tap-event/index.js create mode 100644 node_modules/component-tap-event/package.json create mode 100644 node_modules/component-tween/.npmignore create mode 100644 node_modules/component-tween/History.md create mode 100644 node_modules/component-tween/Makefile create mode 100644 node_modules/component-tween/Readme.md create mode 100644 node_modules/component-tween/component.json create mode 100644 node_modules/component-tween/examples/array.html create mode 100644 node_modules/component-tween/examples/ball.html create mode 100644 node_modules/component-tween/examples/circle.html create mode 100644 node_modules/component-tween/examples/dom.html create mode 100644 node_modules/component-tween/examples/interactive.html create mode 100644 node_modules/component-tween/examples/rect.html create mode 100644 node_modules/component-tween/index.js create mode 100644 node_modules/component-tween/node_modules/component-emitter/History.md create mode 100644 node_modules/component-tween/node_modules/component-emitter/LICENSE create mode 100644 node_modules/component-tween/node_modules/component-emitter/Readme.md create mode 100644 node_modules/component-tween/node_modules/component-emitter/index.js create mode 100644 node_modules/component-tween/node_modules/component-emitter/package.json create mode 100644 node_modules/component-tween/package.json create mode 100644 node_modules/component-type/.npmignore create mode 100644 node_modules/component-type/Makefile create mode 100644 node_modules/component-type/Readme.md create mode 100644 node_modules/component-type/component.json create mode 100644 node_modules/component-type/index.js create mode 100644 node_modules/component-type/package.json create mode 100644 node_modules/component-type/test/index.html create mode 100644 node_modules/component-type/test/mocha.css create mode 100644 node_modules/component-type/test/mocha.js create mode 100644 node_modules/component-type/test/tests.js create mode 100644 node_modules/ease-component/.npmignore create mode 100644 node_modules/ease-component/Makefile create mode 100644 node_modules/ease-component/Readme.md create mode 100644 node_modules/ease-component/component.json create mode 100644 node_modules/ease-component/example.html create mode 100644 node_modules/ease-component/index.js create mode 100644 node_modules/ease-component/package.json create mode 100644 node_modules/global-object/README.md create mode 100644 node_modules/global-object/global-object.js create mode 100644 node_modules/global-object/package.json create mode 100644 node_modules/has-translate3d/.npmignore create mode 100644 node_modules/has-translate3d/History.md create mode 100644 node_modules/has-translate3d/Makefile create mode 100644 node_modules/has-translate3d/Readme.md create mode 100644 node_modules/has-translate3d/component.json create mode 100644 node_modules/has-translate3d/index.js create mode 100644 node_modules/has-translate3d/package.json create mode 100644 node_modules/prop-detect/.travis.yml create mode 100644 node_modules/prop-detect/Makefile create mode 100644 node_modules/prop-detect/Readme.md create mode 100644 node_modules/prop-detect/index.js create mode 100644 node_modules/prop-detect/karma.conf.js create mode 100644 node_modules/prop-detect/package.json create mode 100644 node_modules/prop-detect/test/test.js create mode 100644 node_modules/touchaction-property/.npmignore create mode 100644 node_modules/touchaction-property/History.md create mode 100644 node_modules/touchaction-property/Makefile create mode 100644 node_modules/touchaction-property/Readme.md create mode 100644 node_modules/touchaction-property/component.json create mode 100644 node_modules/touchaction-property/index.js create mode 100644 node_modules/touchaction-property/package.json create mode 100644 node_modules/touchaction-property/test/index.html create mode 100644 node_modules/transform-property/.npmignore create mode 100644 node_modules/transform-property/History.md create mode 100644 node_modules/transform-property/Makefile create mode 100644 node_modules/transform-property/Readme.md create mode 100644 node_modules/transform-property/component.json create mode 100644 node_modules/transform-property/index.js create mode 100644 node_modules/transform-property/package.json create mode 100644 node_modules/transition-property/Makefile create mode 100644 node_modules/transition-property/Readme.md create mode 100644 node_modules/transition-property/index.js create mode 100644 node_modules/transition-property/karma.conf.js create mode 100644 node_modules/transition-property/package.json create mode 100644 node_modules/transition-property/test/test.js diff --git a/1.vim b/1.vim index b0ea6e42..45d4709d 100644 --- a/1.vim +++ b/1.vim @@ -28,10 +28,10 @@ nnoremap \1 :call SN("1") nmap \rn (coc-rename) xmap gx NetrwBrowseXVis nmap gx NetrwBrowseX -snoremap "_c -snoremap c -snoremap c snoremap c +snoremap c +snoremap c +snoremap "_c nnoremap GitGutterPreviewHunk :call gitgutter#utility#warn('Please change your map GitGutterPreviewHunk to (GitGutterPreviewHunk)') nnoremap (GitGutterPreviewHunk) :GitGutterPreviewHunk nnoremap GitGutterUndoHunk :call gitgutter#utility#warn('Please change your map GitGutterUndoHunk to (GitGutterUndoHunk)') @@ -159,17 +159,19 @@ badd +1 src/Model/Utility/utility.ts badd +1 src/View/Modals/dataTransferModal.tsx badd +1 src/View/translations.ts badd +133 src/View/homePage.tsx -badd +1 src/ViewModel/Global/fileTransferViewModel.ts +badd +107 src/ViewModel/Global/fileTransferViewModel.ts badd +10 src/View/Components/homePageButton.tsx -badd +107 src/View/Modals/settingsModal.tsx -badd +0 src/View/Components/navigationButton.tsx +badd +63 src/View/Modals/settingsModal.tsx +badd +1 src/View/Components/navigationButton.tsx +badd +642 dist/styles.css +badd +0 src/ViewModel/Global/coreViewModel.ts argglobal %argdel set stal=2 tabnew +setlocal\ bufhidden=wipe tabnew +setlocal\ bufhidden=wipe tabrewind -edit src/View/Modals/settingsModal.tsx +edit src/ViewModel/Global/coreViewModel.ts let s:save_splitbelow = &splitbelow let s:save_splitright = &splitright set splitbelow splitright @@ -196,13 +198,13 @@ set winminheight=0 set winheight=1 set winminwidth=0 set winwidth=1 -exe 'vert 1resize ' . ((&columns * 54 + 127) / 255) -exe 'vert 2resize ' . ((&columns * 98 + 127) / 255) +exe 'vert 1resize ' . ((&columns * 54 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 61 + 120) / 240) exe '3resize ' . ((&lines * 21 + 23) / 46) -exe 'vert 3resize ' . ((&columns * 97 + 127) / 255) +exe 'vert 3resize ' . ((&columns * 61 + 120) / 240) exe '4resize ' . ((&lines * 21 + 23) / 46) -exe 'vert 4resize ' . ((&columns * 97 + 127) / 255) -exe 'vert 5resize ' . ((&columns * 3 + 127) / 255) +exe 'vert 4resize ' . ((&columns * 61 + 120) / 240) +exe 'vert 5resize ' . ((&columns * 61 + 120) / 240) argglobal enew file NERD_tree_tab_1 @@ -395,7 +397,7 @@ setlocal nowrap setlocal wrapmargin=0 wincmd w argglobal -balt src/View/Components/homePageButton.tsx +balt dist/styles.css let s:cpo_save=&cpo set cpo&vim nmap [c (GitGutterPrevHunk) @@ -445,8 +447,8 @@ setlocal nodiff setlocal equalprg= setlocal errorformat=%+A\ %#%f\ %#(%l\\,%c):\ %m,%C%m setlocal noexpandtab -if &filetype != 'typescriptreact' -setlocal filetype=typescriptreact +if &filetype != 'typescript' +setlocal filetype=typescript endif setlocal fillchars= setlocal fixendofline @@ -469,8 +471,8 @@ setlocal iminsert=0 setlocal imsearch=-1 setlocal include= setlocal includeexpr= -setlocal indentexpr=GetTsxIndent() -setlocal indentkeys=0{,0},0),0],0,,!^F,o,O,e,*,<>>,<<>,/ +setlocal indentexpr=GetTypescriptIndent() +setlocal indentkeys=0{,0},0),0],:,0#,!^F,o,O,e,0],0) setlocal noinfercase setlocal iskeyword=@,48-57,_,192-255,$ setlocal keywordprg= @@ -518,8 +520,8 @@ setlocal statusline= setlocal suffixesadd=.ts,.tsx setlocal swapfile setlocal synmaxcol=3000 -if &syntax != 'typescriptreact' -setlocal syntax=typescriptreact +if &syntax != 'typescript' +setlocal syntax=typescript endif setlocal tabstop=8 setlocal tagcase= @@ -543,12 +545,12 @@ setlocal wrap setlocal wrapmargin=0 silent! normal! zE let &fdl = &fdl -let s:l = 67 - ((18 * winheight(0) + 21) / 43) +let s:l = 29 - ((28 * winheight(0) + 21) / 43) if s:l < 1 | let s:l = 1 | endif keepjumps exe s:l normal! zt -keepjumps 67 -normal! 0 +keepjumps 29 +normal! $ wincmd w argglobal if bufexists(fnamemodify("src/View/Modals/settingsModal.tsx", ":p")) | buffer src/View/Modals/settingsModal.tsx | else | edit src/View/Modals/settingsModal.tsx | endif @@ -700,7 +702,7 @@ setlocal wrap setlocal wrapmargin=0 silent! normal! zE let &fdl = &fdl -let s:l = 109 - ((15 * winheight(0) + 10) / 21) +let s:l = 109 - ((0 * winheight(0) + 10) / 21) if s:l < 1 | let s:l = 1 | endif keepjumps exe s:l normal! zt @@ -857,12 +859,12 @@ setlocal wrap setlocal wrapmargin=0 silent! normal! zE let &fdl = &fdl -let s:l = 15 - ((5 * winheight(0) + 10) / 21) +let s:l = 22 - ((5 * winheight(0) + 10) / 21) if s:l < 1 | let s:l = 1 | endif keepjumps exe s:l normal! zt -keepjumps 15 -normal! 0 +keepjumps 22 +normal! $ wincmd w argglobal if bufexists(fnamemodify("src/Model/Utility/utility.ts", ":p")) | buffer src/Model/Utility/utility.ts | else | edit src/Model/Utility/utility.ts | endif @@ -1021,13 +1023,14 @@ normal! zt keepjumps 233 normal! 017| wincmd w -exe 'vert 1resize ' . ((&columns * 54 + 127) / 255) -exe 'vert 2resize ' . ((&columns * 98 + 127) / 255) +2wincmd w +exe 'vert 1resize ' . ((&columns * 54 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 61 + 120) / 240) exe '3resize ' . ((&lines * 21 + 23) / 46) -exe 'vert 3resize ' . ((&columns * 97 + 127) / 255) +exe 'vert 3resize ' . ((&columns * 61 + 120) / 240) exe '4resize ' . ((&lines * 21 + 23) / 46) -exe 'vert 4resize ' . ((&columns * 97 + 127) / 255) -exe 'vert 5resize ' . ((&columns * 3 + 127) / 255) +exe 'vert 4resize ' . ((&columns * 61 + 120) / 240) +exe 'vert 5resize ' . ((&columns * 61 + 120) / 240) tabnext edit src/View/translations.ts let s:save_splitbelow = &splitbelow @@ -1049,9 +1052,9 @@ set winminheight=0 set winheight=1 set winminwidth=0 set winwidth=1 -exe 'vert 1resize ' . ((&columns * 31 + 127) / 255) -exe 'vert 2resize ' . ((&columns * 111 + 127) / 255) -exe 'vert 3resize ' . ((&columns * 111 + 127) / 255) +exe 'vert 1resize ' . ((&columns * 31 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 111 + 120) / 240) +exe 'vert 3resize ' . ((&columns * 100 + 120) / 240) argglobal enew file NERD_tree_tab_4 @@ -1382,11 +1385,11 @@ setlocal wrap setlocal wrapmargin=0 silent! normal! zE let &fdl = &fdl -let s:l = 706 - ((17 * winheight(0) + 21) / 43) +let s:l = 148 - ((20 * winheight(0) + 21) / 43) if s:l < 1 | let s:l = 1 | endif keepjumps exe s:l normal! zt -keepjumps 706 +keepjumps 148 normal! $ wincmd w argglobal @@ -1394,8 +1397,8 @@ if bufexists(fnamemodify("src/View/Modals/dataTransferModal.tsx", ":p")) | buffe balt src/View/homePage.tsx let s:cpo_save=&cpo set cpo&vim -imap :call coc#snippet#jump(1, 0) imap :call coc#snippet#jump(0, 0) +imap :call coc#snippet#jump(1, 0) nmap [c (GitGutterPrevHunk) nmap \hp (GitGutterPreviewHunk) nmap \hu (GitGutterUndoHunk) @@ -1543,17 +1546,16 @@ setlocal wrap setlocal wrapmargin=0 silent! normal! zE let &fdl = &fdl -let s:l = 12 - ((11 * winheight(0) + 21) / 43) +let s:l = 734 - ((38 * winheight(0) + 21) / 43) if s:l < 1 | let s:l = 1 | endif keepjumps exe s:l normal! zt -keepjumps 12 -normal! $ +keepjumps 734 +normal! 022| wincmd w -3wincmd w -exe 'vert 1resize ' . ((&columns * 31 + 127) / 255) -exe 'vert 2resize ' . ((&columns * 111 + 127) / 255) -exe 'vert 3resize ' . ((&columns * 111 + 127) / 255) +exe 'vert 1resize ' . ((&columns * 31 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 111 + 120) / 240) +exe 'vert 3resize ' . ((&columns * 100 + 120) / 240) tabnext edit src/ViewModel/Global/fileTransferViewModel.ts let s:save_splitbelow = &splitbelow @@ -1561,7 +1563,14 @@ let s:save_splitright = &splitright set splitbelow splitright wincmd _ | wincmd | vsplit -1wincmd h +wincmd _ | wincmd | +vsplit +2wincmd h +wincmd w +wincmd w +wincmd _ | wincmd | +split +1wincmd k wincmd w let &splitbelow = s:save_splitbelow let &splitright = s:save_splitright @@ -1572,8 +1581,12 @@ set winminheight=0 set winheight=1 set winminwidth=0 set winwidth=1 -exe 'vert 1resize ' . ((&columns * 31 + 127) / 255) -exe 'vert 2resize ' . ((&columns * 223 + 127) / 255) +exe 'vert 1resize ' . ((&columns * 31 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 104 + 120) / 240) +exe '3resize ' . ((&lines * 21 + 23) / 46) +exe 'vert 3resize ' . ((&columns * 103 + 120) / 240) +exe '4resize ' . ((&lines * 21 + 23) / 46) +exe 'vert 4resize ' . ((&columns * 103 + 120) / 240) argglobal enew file NERD_tree_tab_3 @@ -1914,16 +1927,334 @@ setlocal wrap setlocal wrapmargin=0 silent! normal! zE let &fdl = &fdl -let s:l = 139 - ((9 * winheight(0) + 21) / 43) +let s:l = 176 - ((17 * winheight(0) + 21) / 43) if s:l < 1 | let s:l = 1 | endif keepjumps exe s:l normal! zt -keepjumps 139 +keepjumps 176 normal! $ wincmd w -exe 'vert 1resize ' . ((&columns * 31 + 127) / 255) -exe 'vert 2resize ' . ((&columns * 223 + 127) / 255) -tabnext 2 +argglobal +if bufexists(fnamemodify("src/Model/Global/fileTransferModel.ts", ":p")) | buffer src/Model/Global/fileTransferModel.ts | else | edit src/Model/Global/fileTransferModel.ts | endif +balt src/ViewModel/Global/fileTransferViewModel.ts +let s:cpo_save=&cpo +set cpo&vim +nmap [c (GitGutterPrevHunk) +nmap \hp (GitGutterPreviewHunk) +nmap \hu (GitGutterUndoHunk) +nmap \hs (GitGutterStageHunk) +xmap \hs (GitGutterStageHunk) +nmap ]c (GitGutterNextHunk) +xmap ac (GitGutterTextObjectOuterVisual) +omap ac (GitGutterTextObjectOuterPending) +xmap ic (GitGutterTextObjectInnerVisual) +omap ic (GitGutterTextObjectInnerPending) +let &cpo=s:cpo_save +unlet s:cpo_save +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal backupcopy= +setlocal balloonexpr= +setlocal nobinary +setlocal nobreakindent +setlocal breakindentopt= +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),0],:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinscopedecls=public,protected,private +setlocal cinwords=if,else,while,do,for,switch +setlocal colorcolumn= +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=//\ %s +setlocal complete=.,w,b,u,t,i +setlocal concealcursor= +setlocal conceallevel=0 +setlocal completefunc= +setlocal nocopyindent +setlocal cryptmethod= +setlocal nocursorbind +setlocal nocursorcolumn +setlocal nocursorline +setlocal cursorlineopt=both +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat=%+A\ %#%f\ %#(%l\\,%c):\ %m,%C%m +setlocal noexpandtab +if &filetype != 'typescript' +setlocal filetype=typescript +endif +setlocal fillchars= +setlocal fixendofline +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=croql +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal formatprg= +setlocal grepprg= +setlocal iminsert=0 +setlocal imsearch=-1 +setlocal include= +setlocal includeexpr= +setlocal indentexpr=GetTypescriptIndent() +setlocal indentkeys=0{,0},0),0],:,0#,!^F,o,O,e,0],0) +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255,$ +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal lispoptions= +setlocal lispwords= +setlocal nolist +setlocal listchars= +setlocal makeencoding= +setlocal makeprg=tsc\ \ $*\ % +setlocal matchpairs=(:),{:},[:] +setlocal nomodeline +setlocal modifiable +setlocal nrformats=bin,octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norelativenumber +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal scrolloff=-1 +setlocal shiftwidth=4 +setlocal noshortname +setlocal showbreak= +setlocal sidescrolloff=-1 +set signcolumn=yes +setlocal signcolumn=yes +setlocal nosmartindent +setlocal nosmoothscroll +setlocal softtabstop=0 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal spelloptions= +setlocal statusline= +setlocal suffixesadd=.ts,.tsx +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'typescript' +setlocal syntax=typescript +endif +setlocal tabstop=8 +setlocal tagcase= +setlocal tagfunc= +setlocal tags= +setlocal termwinkey= +setlocal termwinscroll=10000 +setlocal termwinsize= +setlocal textwidth=0 +setlocal thesaurus= +setlocal thesaurusfunc= +setlocal noundofile +setlocal undolevels=-123456 +setlocal varsofttabstop= +setlocal vartabstop= +setlocal virtualedit= +setlocal wincolor= +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let &fdl = &fdl +let s:l = 130 - ((12 * winheight(0) + 10) / 21) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 130 +normal! 017| +wincmd w +argglobal +if bufexists(fnamemodify("src/Model/Global/fileTransferModel.ts", ":p")) | buffer src/Model/Global/fileTransferModel.ts | else | edit src/Model/Global/fileTransferModel.ts | endif +balt src/ViewModel/Global/fileTransferViewModel.ts +let s:cpo_save=&cpo +set cpo&vim +nmap [c (GitGutterPrevHunk) +nmap \hp (GitGutterPreviewHunk) +nmap \hu (GitGutterUndoHunk) +nmap \hs (GitGutterStageHunk) +xmap \hs (GitGutterStageHunk) +nmap ]c (GitGutterNextHunk) +xmap ac (GitGutterTextObjectOuterVisual) +omap ac (GitGutterTextObjectOuterPending) +xmap ic (GitGutterTextObjectInnerVisual) +omap ic (GitGutterTextObjectInnerPending) +let &cpo=s:cpo_save +unlet s:cpo_save +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal backupcopy= +setlocal balloonexpr= +setlocal nobinary +setlocal nobreakindent +setlocal breakindentopt= +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),0],:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinscopedecls=public,protected,private +setlocal cinwords=if,else,while,do,for,switch +setlocal colorcolumn= +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=//\ %s +setlocal complete=.,w,b,u,t,i +setlocal concealcursor= +setlocal conceallevel=0 +setlocal completefunc= +setlocal nocopyindent +setlocal cryptmethod= +setlocal nocursorbind +setlocal nocursorcolumn +setlocal nocursorline +setlocal cursorlineopt=both +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat=%+A\ %#%f\ %#(%l\\,%c):\ %m,%C%m +setlocal noexpandtab +if &filetype != 'typescript' +setlocal filetype=typescript +endif +setlocal fillchars= +setlocal fixendofline +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=croql +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal formatprg= +setlocal grepprg= +setlocal iminsert=0 +setlocal imsearch=-1 +setlocal include= +setlocal includeexpr= +setlocal indentexpr=GetTypescriptIndent() +setlocal indentkeys=0{,0},0),0],:,0#,!^F,o,O,e,0],0) +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255,$ +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal lispoptions= +setlocal lispwords= +setlocal nolist +setlocal listchars= +setlocal makeencoding= +setlocal makeprg=tsc\ \ $*\ % +setlocal matchpairs=(:),{:},[:] +setlocal nomodeline +setlocal modifiable +setlocal nrformats=bin,octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norelativenumber +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal scrolloff=-1 +setlocal shiftwidth=4 +setlocal noshortname +setlocal showbreak= +setlocal sidescrolloff=-1 +set signcolumn=yes +setlocal signcolumn=yes +setlocal nosmartindent +setlocal nosmoothscroll +setlocal softtabstop=0 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal spelloptions= +setlocal statusline= +setlocal suffixesadd=.ts,.tsx +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'typescript' +setlocal syntax=typescript +endif +setlocal tabstop=8 +setlocal tagcase= +setlocal tagfunc= +setlocal tags= +setlocal termwinkey= +setlocal termwinscroll=10000 +setlocal termwinsize= +setlocal textwidth=0 +setlocal thesaurus= +setlocal thesaurusfunc= +setlocal noundofile +setlocal undolevels=-123456 +setlocal varsofttabstop= +setlocal vartabstop= +setlocal virtualedit= +setlocal wincolor= +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let &fdl = &fdl +let s:l = 166 - ((9 * winheight(0) + 10) / 21) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 166 +normal! $ +wincmd w +exe 'vert 1resize ' . ((&columns * 31 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 104 + 120) / 240) +exe '3resize ' . ((&lines * 21 + 23) / 46) +exe 'vert 3resize ' . ((&columns * 103 + 120) / 240) +exe '4resize ' . ((&lines * 21 + 23) / 46) +exe 'vert 4resize ' . ((&columns * 103 + 120) / 240) +tabnext 1 set stal=1 if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 silent exe 'bwipe ' . s:wipebuf diff --git a/dist/index.css b/dist/index.css index adc6b87d..b2c172cb 100644 --- a/dist/index.css +++ b/dist/index.css @@ -492,9 +492,13 @@ body[showing-chat] #chat-page-wrapper { gap: var(--large-gap); width: 100%; height: 100%; - overflow: auto; + overflow: visible; + transform-origin: top left; padding: var(--content-padding); } +#board-content .main-content { + overflow: auto; +} #chat-page > div > #main > #task-page .kanban-board-wrapper .kanban-column, #chat-page > div > #main > #task-page .status-grid-wrapper .status-column { display: flex; diff --git a/dist/index.js b/dist/index.js index 6f71f13e..e507e5c5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1136,6 +1136,34 @@ function localeCompare(a, b) { return a.localeCompare(b); } + function implementPinchZoom(element) { + let initialDistance = 0; + let pinching = false; + const distance = (e) => Math.hypot( + e.touches[0].pageX - e.touches[1].pageX, + e.touches[0].pageY - e.touches[1].pageY + ); + function apply(factor) { + element.style.transform = `scale(${(Math.floor(factor * 100) / 100).toString()})`; + } + element.addEventListener("touchstart", (event) => { + if (event.touches.length != 2) return; + initialDistance = distance(event); + pinching = true; + apply(1); + }); + element.addEventListener("touchend", (event) => { + if (event.touches.length == 2) return; + pinching = false; + }); + element.addEventListener("touchmove", (event) => { + if (!pinching) return; + event.preventDefault(); + const currentDistance = distance(event); + const factor = currentDistance / initialDistance; + apply(factor); + }); + } // src/ViewModel/Global/coreViewModel.ts var CoreViewModel = class _CoreViewModel { @@ -1146,7 +1174,7 @@ this.connectionModel = connectionModel2; this.chatListModel = chatListModel2; this.fileTransferModel = fileTransferModel2; - this.BUILD = "Build 26.08.30.B"; + this.BUILD = "Build 26.08.30.C"; // CONTEXT this.contextStack = /* @__PURE__ */ new Map(); this.closeContext = (contextId, fromHistoryEvent = false) => { @@ -4879,7 +4907,7 @@ const index = createPropertyValueIndexState(sortedStatuses, statusName); return StatusNameCell(coreViewModel2, statusName, index, boardViewModel); }; - return /* @__PURE__ */ createElement("div", { class: "status-page-content" }, /* @__PURE__ */ createElement( + const main = /* @__PURE__ */ createElement("div", { class: "status-page-content" }, /* @__PURE__ */ createElement( "div", { class: "status-name-row", @@ -4913,6 +4941,8 @@ ); } )); + implementPinchZoom(main); + return main; } function StatusNameCell(coreViewModel2, statusName, index, boardViewModel) { const taskViewModelsWithMatchingStatus = new ListState(); @@ -5036,7 +5066,7 @@ // src/View/ChatPages/boardKanbanPage.tsx function BoardKanbanPage(coreViewModel2, boardViewModel) { - return PropertyValueList( + const main = PropertyValueList( "category", (taskViewModel) => taskViewModel.task, boardViewModel.filteredTaskViewModels, @@ -5062,6 +5092,8 @@ ); } ); + implementPinchZoom(main); + return main; } function Column(coreViewModel2, categoryName, index, boardViewModel) { return FilteredList( diff --git a/dist/sw.js b/dist/sw.js index ceefd51c..6cf43b4d 100644 --- a/dist/sw.js +++ b/dist/sw.js @@ -1,4 +1,4 @@ -const CACHE_VERSION = "v2"; +const CACHE_VERSION = "26.08.30.C"; self.addEventListener("fetch", (event) => { event.respondWith(handleRequest(event)); diff --git a/node_modules/component-clone/.npmignore b/node_modules/component-clone/.npmignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/node_modules/component-clone/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/component-clone/History.md b/node_modules/component-clone/History.md new file mode 100644 index 00000000..9ecdf547 --- /dev/null +++ b/node_modules/component-clone/History.md @@ -0,0 +1,28 @@ + +0.2.2 / 2014-03-06 +================== + + * fix require() call again + +0.2.1 / 2014-03-01 +================== + + * make clone work in all environments FOR REAL + * change npm name to component-clone + +0.2.0 / 2014-01-27 +================== + + * make clone work in all environments + +0.1.1 / 2014-01-07 +================== + + * add repo field to component.json + * add tests around cloning functions + * package: fixed package.json + +0.1.0 / 2012-10-18 +================== + + * initial release diff --git a/node_modules/component-clone/Makefile b/node_modules/component-clone/Makefile new file mode 100644 index 00000000..a31c14cf --- /dev/null +++ b/node_modules/component-clone/Makefile @@ -0,0 +1,9 @@ + +REPORTER = dot + +test: + @./node_modules/.bin/mocha \ + --reporter $(REPORTER) \ + --bail + +.PHONY: test diff --git a/node_modules/component-clone/Readme.md b/node_modules/component-clone/Readme.md new file mode 100644 index 00000000..685ecaee --- /dev/null +++ b/node_modules/component-clone/Readme.md @@ -0,0 +1,27 @@ + +# clone + + Object clone supporting `date`, `regexp`, `array` and `object` types. + +## Example + +```js +var obj = clone({ + a: 'b', + c: [ + new Date(), + 'tobi', + 'jane' + ] +}) +``` + +## API + +### clone(obj) + + Clones `obj` recursively and returns it. + +## License + +MIT diff --git a/node_modules/component-clone/component.json b/node_modules/component-clone/component.json new file mode 100644 index 00000000..73037758 --- /dev/null +++ b/node_modules/component-clone/component.json @@ -0,0 +1,15 @@ +{ + "name": "clone", + "repo": "component/clone", + "version": "0.2.2", + "dependencies": { + "component/type": "*" + }, + "devDependencies": { + "visionmedia/mocha": "*", + "guille/expect.js": "*" + }, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-clone/index.js b/node_modules/component-clone/index.js new file mode 100644 index 00000000..a74bc22b --- /dev/null +++ b/node_modules/component-clone/index.js @@ -0,0 +1,57 @@ +/** + * Module dependencies. + */ + +var type; +try { + type = require('component-type'); +} catch (_) { + type = require('type'); +} + +/** + * Module exports. + */ + +module.exports = clone; + +/** + * Clones objects. + * + * @param {Mixed} any object + * @api public + */ + +function clone(obj){ + switch (type(obj)) { + case 'object': + var copy = {}; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + copy[key] = clone(obj[key]); + } + } + return copy; + + case 'array': + var copy = new Array(obj.length); + for (var i = 0, l = obj.length; i < l; i++) { + copy[i] = clone(obj[i]); + } + return copy; + + case 'regexp': + // from millermedeiros/amd-utils - MIT + var flags = ''; + flags += obj.multiline ? 'm' : ''; + flags += obj.global ? 'g' : ''; + flags += obj.ignoreCase ? 'i' : ''; + return new RegExp(obj.source, flags); + + case 'date': + return new Date(obj.getTime()); + + default: // string, number, boolean, … + return obj; + } +} diff --git a/node_modules/component-clone/package.json b/node_modules/component-clone/package.json new file mode 100644 index 00000000..f61c557e --- /dev/null +++ b/node_modules/component-clone/package.json @@ -0,0 +1,26 @@ +{ + "name": "component-clone", + "version": "0.2.2", + "dependencies": { + "component-type": "*" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "component": { + "scripts": { + "clone/index.js": "index.js" + } + }, + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "https://github.com/component/clone.git" + }, + "browser": { + "type": "component-type" + } +} diff --git a/node_modules/component-clone/test/clone.js b/node_modules/component-clone/test/clone.js new file mode 100644 index 00000000..bcd2cf8f --- /dev/null +++ b/node_modules/component-clone/test/clone.js @@ -0,0 +1,80 @@ + +/* test dependencies */ + +var clone = require('..'); +var expect = require('expect.js'); + +/* tests */ + +describe('clone', function(){ + + it('date', function(){ + var obj = new Date; + var cloned = clone(obj); + expect(cloned.getTime()).to.be(obj.getTime()); + expect(cloned).not.to.be(obj); + }); + + it('regexp', function(){ + var obj = /hello/i; + var cloned = clone(obj); + expect(cloned.toString()).to.be(obj.toString()); + expect(cloned).not.to.be(obj); + }); + + it('array', function(){ + var obj = [1, 2, 3, '4']; + var cloned = clone(obj); + expect(cloned).to.eql(obj); + expect(cloned).not.to.be(obj); + }); + + it('object', function(){ + var obj = { + a: 1, + b: 2, + c: 3 + }; + var cloned = clone(obj); + expect(cloned).to.eql(obj); + expect(cloned).not.to.be(obj); + }); + + it('object combined', function(){ + var date = new Date; + var obj = { + a: { + b: [1, 2, date, { hello: 'world' }] + } + }; + var cloned = clone(obj); + expect(cloned).to.eql(obj); + expect(cloned.a).not.to.be(obj.a); + expect(cloned.a.b).not.to.be(obj.a.b); + expect(cloned.a.b[2]).not.to.be(obj.a.b[2]); + expect(cloned.a.b[2].getTime()).to.be(obj.a.b[2].getTime()); + expect(cloned.a.b[3]).to.eql(obj.a.b[3]); + expect(cloned.a.b[3]).not.to.be(obj.a.b[3]); + }); + + it('object with functions', function() { + var func = function () { return 'original'; }; + var host = { fluent: func }; + var cloned = clone(host); + + // cloned function matches original + + expect(cloned.fluent).to.be(func); + + // change cloned function (no longer matches original) + + cloned.fluent = function () { return 'updated'; }; + expect(cloned.fluent).not.to.be(func); + expect(cloned.fluent()).to.be('updated'); + + // original function is still in place + + expect(func()).to.be('original'); + }); + +}); diff --git a/node_modules/component-closest/.npmignore b/node_modules/component-closest/.npmignore new file mode 100644 index 00000000..f62e6050 --- /dev/null +++ b/node_modules/component-closest/.npmignore @@ -0,0 +1,59 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store* +ehthumbs.db +Icon? +Thumbs.db + +# Node.js # +########### +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +node_modules +npm-debug.log + +# Components # +############## + +/build +/components +/vendors \ No newline at end of file diff --git a/node_modules/component-closest/History.md b/node_modules/component-closest/History.md new file mode 100644 index 00000000..002fa756 --- /dev/null +++ b/node_modules/component-closest/History.md @@ -0,0 +1,28 @@ + +1.0.1 / 2016-04-01 +================== + + * component, package: bump matches-selector dependency to 0.1.6 (#4, @ockham) + * index: fall back to `require('component-matches-selector')` (#3, @ockham) + +1.0.0 / 2015-07-15 +================== + + * BREAKING: rewrite to always check self. If you need the old functionality, do closest(el.parentNode, ...) + +0.1.4 / 2014-07-27 +================== + + * test: add TextNode closest() test case + * component, package: pin "matches-selector" to v0.1.5 + * component, package: fix "repository" URL + * package: rename to "component-closest" for npm + * index: fix whitespace + +0.1.3 / 2014-05-27 +================== + + * package: add "browser" section for browserify + * package: add "author" field + * package: add "repository" field + * add `package.json` file diff --git a/node_modules/component-closest/Makefile b/node_modules/component-closest/Makefile new file mode 100644 index 00000000..c2302723 --- /dev/null +++ b/node_modules/component-closest/Makefile @@ -0,0 +1,5 @@ +build: + component install + component build + +.PHONY: build \ No newline at end of file diff --git a/node_modules/component-closest/README.md b/node_modules/component-closest/README.md new file mode 100644 index 00000000..3cb452e8 --- /dev/null +++ b/node_modules/component-closest/README.md @@ -0,0 +1,44 @@ +# Closest + +Similar to jQuery's `$.fn.closest` and `$.fn.parents`. +Finds the closest parent that matches a selector. + +## API + +### closest(element, selector, scope) + +* `element` - will check this elements parents +* `selector` - CSS selector to match parents +* `scope` - check this element and within. By default, `document.documentElement`. + +Example: + +```js +closest(document.body, 'html') === document.documentElement +closest(document.body, 'body') === document.body +closest(document.documentElement, 'body') == null +``` + +## License + +The MIT License (MIT) + +Copyright (c) 2013 Jonathan Ong me@jongleberry.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/component-closest/component.json b/node_modules/component-closest/component.json new file mode 100644 index 00000000..3e3e53d1 --- /dev/null +++ b/node_modules/component-closest/component.json @@ -0,0 +1,14 @@ +{ + "name": "closest", + "description": "Find the closest ancestor matching a selector string", + "version": "1.0.1", + "repo": "component/closest", + "dependencies": { + "component/matches-selector": "0.1.6" + }, + "main": "index.js", + "scripts": [ + "index.js" + ], + "license": "MIT" +} diff --git a/node_modules/component-closest/index.js b/node_modules/component-closest/index.js new file mode 100644 index 00000000..97c2982c --- /dev/null +++ b/node_modules/component-closest/index.js @@ -0,0 +1,36 @@ +/** + * Module Dependencies + */ + +try { + var matches = require('matches-selector') +} catch (err) { + var matches = require('component-matches-selector') +} + +/** + * Export `closest` + */ + +module.exports = closest + +/** + * Closest + * + * @param {Element} el + * @param {String} selector + * @param {Element} scope (optional) + */ + +function closest (el, selector, scope) { + scope = scope || document.documentElement; + + // walk up the dom + while (el && el !== scope) { + if (matches(el, selector)) return el; + el = el.parentNode; + } + + // check scope for match + return matches(el, selector) ? el : null; +} diff --git a/node_modules/component-closest/package.json b/node_modules/component-closest/package.json new file mode 100644 index 00000000..c71451d8 --- /dev/null +++ b/node_modules/component-closest/package.json @@ -0,0 +1,23 @@ +{ + "name": "component-closest", + "description": "Find the closest ancestor matching a selector string", + "version": "1.0.1", + "author": "Jonathan Ong", + "dependencies": { + "component-matches-selector": "~0.1.6" + }, + "browser": { + "matches-selector": "component-matches-selector" + }, + "component": { + "scripts": { + "closest/index.js": "index.js" + } + }, + "main": "index.js", + "license": "MIT", + "repository": { + "type": "git", + "url": "git://github.com/component/closest.git" + } +} diff --git a/node_modules/component-closest/test/index.html b/node_modules/component-closest/test/index.html new file mode 100644 index 00000000..ab17d607 --- /dev/null +++ b/node_modules/component-closest/test/index.html @@ -0,0 +1,45 @@ + + + + + closest + + + +
+
+
hello
+
+
+ + + diff --git a/node_modules/component-delegate/.npmignore b/node_modules/component-delegate/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/component-delegate/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/component-delegate/History.md b/node_modules/component-delegate/History.md new file mode 100644 index 00000000..5e0452e8 --- /dev/null +++ b/node_modules/component-delegate/History.md @@ -0,0 +1,34 @@ + +0.2.4 / 2016-04-01 +================== + + * index: fall back to require('component-*') for node compat + +0.2.3 / 2014-08-01 +================== + + * component, package: use "component/closest" + +0.2.2 / 2014-05-27 +================== + + * add package.json file + * component: beautify "keywords" + +0.2.1 / 2013-10-02 +================== + + * optimize closest + +0.2.0 / 2013-09-30 +================== + + * delegate child elements, closes #3 + * Fixed e.target for IE [anthonyshort] + * Use `call()` to correctly assign `this` in handler [necolas] + * remove weird dead code. Closes #4 + +0.1.0 / 2012-12-19 +================== + + * add "event" dependency for x-browser diff --git a/node_modules/component-delegate/Makefile b/node_modules/component-delegate/Makefile new file mode 100644 index 00000000..b3770fb1 --- /dev/null +++ b/node_modules/component-delegate/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build + +components: component.json + @component install --dev + +clean: + rm -fr build components + +.PHONY: clean diff --git a/node_modules/component-delegate/Readme.md b/node_modules/component-delegate/Readme.md new file mode 100644 index 00000000..4e506855 --- /dev/null +++ b/node_modules/component-delegate/Readme.md @@ -0,0 +1,39 @@ + +# delegate + + Low-level event delegation component. + +## Installation + + $ component install component/delegate + +## Example + +```js +var delegate = require('delegate'); +var ul = document.querySelector('ul'); +var n = 0; + +var fn = delegate.bind(ul, 'li a', 'click', function(e){ + console.log(e.target); + console.log(e.delegateTarget); // => "" + if (++n == 3) { + console.log('unbind'); + delegate.unbind(ul, 'click', fn, false); + } +}, false); +``` + +## API + +### .bind(el, selector, type, callback, [capture]) + + Bind and return a callback which may be passed to `.unbind()`. + +### .unbind(el, type, callback, [capture]) + + Unbind. + +## License + + MIT diff --git a/node_modules/component-delegate/component.json b/node_modules/component-delegate/component.json new file mode 100644 index 00000000..a69e8ea2 --- /dev/null +++ b/node_modules/component-delegate/component.json @@ -0,0 +1,19 @@ +{ + "name": "delegate", + "repo": "component/delegate", + "description": "Event delegation component", + "version": "0.2.4", + "keywords": [ + "event", + "events", + "delegate", + "delegation" + ], + "dependencies": { + "component/closest": "*", + "component/event": "*" + }, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-delegate/index.js b/node_modules/component-delegate/index.js new file mode 100644 index 00000000..f20bb6c7 --- /dev/null +++ b/node_modules/component-delegate/index.js @@ -0,0 +1,51 @@ +/** + * Module dependencies. + */ + +try { + var closest = require('closest'); +} catch(err) { + var closest = require('component-closest'); +} + +try { + var event = require('event'); +} catch(err) { + var event = require('component-event'); +} + +/** + * Delegate event `type` to `selector` + * and invoke `fn(e)`. A callback function + * is returned which may be passed to `.unbind()`. + * + * @param {Element} el + * @param {String} selector + * @param {String} type + * @param {Function} fn + * @param {Boolean} capture + * @return {Function} + * @api public + */ + +exports.bind = function(el, selector, type, fn, capture){ + return event.bind(el, type, function(e){ + var target = e.target || e.srcElement; + e.delegateTarget = closest(target, selector, true, el); + if (e.delegateTarget) fn.call(el, e); + }, capture); +}; + +/** + * Unbind event `type`'s callback `fn`. + * + * @param {Element} el + * @param {String} type + * @param {Function} fn + * @param {Boolean} capture + * @api public + */ + +exports.unbind = function(el, type, fn, capture){ + event.unbind(el, type, fn, capture); +}; diff --git a/node_modules/component-delegate/package.json b/node_modules/component-delegate/package.json new file mode 100644 index 00000000..47e9c70a --- /dev/null +++ b/node_modules/component-delegate/package.json @@ -0,0 +1,28 @@ +{ + "name": "component-delegate", + "description": "Event delegation component", + "version": "0.2.4", + "keywords": [ + "event", + "events", + "delegate", + "delegation" + ], + "dependencies": { + "component-closest": "*", + "component-event": "*" + }, + "browser": { + "closest": "component-closest", + "event": "component-event" + }, + "component": { + "scripts": { + "delegate/index.js": "index.js" + } + }, + "repository": { + "type": "git", + "url": "git://github.com/component/delegate.git" + } +} diff --git a/node_modules/component-delegate/test/index.html b/node_modules/component-delegate/test/index.html new file mode 100644 index 00000000..592b7507 --- /dev/null +++ b/node_modules/component-delegate/test/index.html @@ -0,0 +1,55 @@ + + + Event + + + + + + + +
    +
  • one
  • +
+ + + + + + + + diff --git a/node_modules/component-emitter/LICENSE b/node_modules/component-emitter/LICENSE new file mode 100644 index 00000000..de516927 --- /dev/null +++ b/node_modules/component-emitter/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2014 Component contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/component-emitter/Readme.md b/node_modules/component-emitter/Readme.md new file mode 100644 index 00000000..0f3f9b9f --- /dev/null +++ b/node_modules/component-emitter/Readme.md @@ -0,0 +1,74 @@ +# Emitter [![Build Status](https://travis-ci.org/component/emitter.png)](https://travis-ci.org/component/emitter) + + Event emitter component. + +## Installation + +``` +$ component install component/emitter +``` + +## API + +### Emitter(obj) + + The `Emitter` may also be used as a mixin. For example + a "plain" object may become an emitter, or you may + extend an existing prototype. + + As an `Emitter` instance: + +```js +var Emitter = require('emitter'); +var emitter = new Emitter; +emitter.emit('something'); +``` + + As a mixin: + +```js +var Emitter = require('emitter'); +var user = { name: 'tobi' }; +Emitter(user); + +user.emit('im a user'); +``` + + As a prototype mixin: + +```js +var Emitter = require('emitter'); +Emitter(User.prototype); +``` + +### Emitter#on(event, fn) + + Register an `event` handler `fn`. + +### Emitter#once(event, fn) + + Register a single-shot `event` handler `fn`, + removed immediately after it is invoked the + first time. + +### Emitter#off(event, fn) + + * Pass `event` and `fn` to remove a listener. + * Pass `event` to remove all listeners on that event. + * Pass nothing to remove all listeners on all events. + +### Emitter#emit(event, ...) + + Emit an `event` with variable option args. + +### Emitter#listeners(event) + + Return an array of callbacks, or an empty array. + +### Emitter#hasListeners(event) + + Check if this emitter has `event` handlers. + +## License + +MIT diff --git a/node_modules/component-emitter/index.js b/node_modules/component-emitter/index.js new file mode 100644 index 00000000..6d7ed0ab --- /dev/null +++ b/node_modules/component-emitter/index.js @@ -0,0 +1,175 @@ + +/** + * Expose `Emitter`. + */ + +if (typeof module !== 'undefined') { + module.exports = Emitter; +} + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = +Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = +Emitter.prototype.removeListener = +Emitter.prototype.removeAllListeners = +Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + + // Remove event specific arrays for event types that no + // one is subscribed for to avoid memory leak. + if (callbacks.length === 0) { + delete this._callbacks['$' + event]; + } + + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + + var args = new Array(arguments.length - 1) + , callbacks = this._callbacks['$' + event]; + + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; diff --git a/node_modules/component-emitter/package.json b/node_modules/component-emitter/package.json new file mode 100644 index 00000000..0b8eca97 --- /dev/null +++ b/node_modules/component-emitter/package.json @@ -0,0 +1,28 @@ +{ + "name": "component-emitter", + "description": "Event emitter", + "version": "1.3.1", + "license": "MIT", + "funding": "https://github.com/sponsors/sindresorhus", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "component": { + "scripts": { + "emitter/index.js": "index.js" + } + }, + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/component-emitter.git" + }, + "scripts": { + "test": "make test" + }, + "files": [ + "index.js", + "LICENSE" + ] +} diff --git a/node_modules/component-event/.npmignore b/node_modules/component-event/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/component-event/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/component-event/History.md b/node_modules/component-event/History.md new file mode 100644 index 00000000..6651d245 --- /dev/null +++ b/node_modules/component-event/History.md @@ -0,0 +1,28 @@ + +0.1.4 / 2014-05-27 +================== + + * component, package: add "browser" as a keyword + * package: remove "repo" field + +0.1.3 / 2014-02-10 +================== + + * package: rename module to "component-event" + +0.1.2 / 2013-12-01 +================== + + * package: add "repository" field + * check if addEventListener method is supported by the browser, just once + * test: update to test in IE7+ + +0.1.1 / 2013-08-16 +================== + + * fix: default `capture` to `false` + +0.1.0 / 2012-12-18 +================== + + * add returning of the callback function diff --git a/node_modules/component-event/Makefile b/node_modules/component-event/Makefile new file mode 100644 index 00000000..b3770fb1 --- /dev/null +++ b/node_modules/component-event/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build + +components: component.json + @component install --dev + +clean: + rm -fr build components + +.PHONY: clean diff --git a/node_modules/component-event/Readme.md b/node_modules/component-event/Readme.md new file mode 100644 index 00000000..7a22983f --- /dev/null +++ b/node_modules/component-event/Readme.md @@ -0,0 +1,39 @@ + +# event + + Element event binding component. + +## Installation + + $ component install component/event + +## Example + +```js +var events = require('event'); +var a = document.querySelector('a'); + +function onclick(e) { + e.preventDefault(); + console.log(e.target); + events.unbind(a, 'click', onclick); +} + +events.bind(a, 'click', onclick); +``` + +## API + +### .bind(el, type, callback, [capture]) + + Bind to `el`'s event `type` with `callback`, + returns the `callback` passed. + +### .unbind(el, type, callback, [capture]) + + Unbind `el`'s event `type` `callback`, + returns the `callback` passed. + +## License + + MIT diff --git a/node_modules/component-event/component.json b/node_modules/component-event/component.json new file mode 100644 index 00000000..d6e81fa7 --- /dev/null +++ b/node_modules/component-event/component.json @@ -0,0 +1,14 @@ +{ + "name": "event", + "repo": "component/event", + "description": "Event binding component", + "version": "0.1.4", + "keywords": [ + "browser", + "event", + "events" + ], + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-event/index.js b/node_modules/component-event/index.js new file mode 100644 index 00000000..ef05d5c4 --- /dev/null +++ b/node_modules/component-event/index.js @@ -0,0 +1,35 @@ +var bind = window.addEventListener ? 'addEventListener' : 'attachEvent', + unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent', + prefix = bind !== 'addEventListener' ? 'on' : ''; + +/** + * Bind `el` event `type` to `fn`. + * + * @param {Element} el + * @param {String} type + * @param {Function} fn + * @param {Boolean} capture + * @return {Function} + * @api public + */ + +exports.bind = function(el, type, fn, capture){ + el[bind](prefix + type, fn, capture || false); + return fn; +}; + +/** + * Unbind `el` event `type`'s callback `fn`. + * + * @param {Element} el + * @param {String} type + * @param {Function} fn + * @param {Boolean} capture + * @return {Function} + * @api public + */ + +exports.unbind = function(el, type, fn, capture){ + el[unbind](prefix + type, fn, capture || false); + return fn; +}; \ No newline at end of file diff --git a/node_modules/component-event/package.json b/node_modules/component-event/package.json new file mode 100644 index 00000000..93f725ce --- /dev/null +++ b/node_modules/component-event/package.json @@ -0,0 +1,19 @@ +{ + "name": "component-event", + "description": "Event binding component", + "version": "0.1.4", + "keywords": [ + "browser", + "event", + "events" + ], + "component": { + "scripts": { + "event/index.js": "index.js" + } + }, + "repository": { + "type": "git", + "url": "https://github.com/component/event.git" + } +} diff --git a/node_modules/component-event/test/index.html b/node_modules/component-event/test/index.html new file mode 100644 index 00000000..b22c85e9 --- /dev/null +++ b/node_modules/component-event/test/index.html @@ -0,0 +1,33 @@ + + + Event + + + + link + + + + + + \ No newline at end of file diff --git a/node_modules/component-events/.npmignore b/node_modules/component-events/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/component-events/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/component-events/History.md b/node_modules/component-events/History.md new file mode 100644 index 00000000..666f361e --- /dev/null +++ b/node_modules/component-events/History.md @@ -0,0 +1,53 @@ + +1.0.10 / 2014-04-01 +================== + + * component, package: bump component-delegate dependency to 0.2.4 + * index: Fall back to require('component-*') for node compat + +1.0.9 / 2014-08-01 +================== + + * component, package: update "delegate" to v0.2.3 + +1.0.8 / 2014-07-21 +================== + + * component, package: update "event" to v0.1.4 + +1.0.7 / 2014-05-27 +================== + + * component, package: update "component/delegate" to v0.2.2 + +1.0.6 / 2014-02-10 +================== + + * package: rename to "component-events" + * component: update "event" to v0.1.3 + +1.0.5 / 2014-01-22 +================== + + * update deps + +1.0.4 / 2013-07-28 +================== + + * add delegation support and inline manager + +1.0.3 / 2013-05-27 +================== + + * pin deps + * rename for broken npm tooling + +1.0.2 / 2013-01-08 +================== + + * fix unbind + +1.0.1 / 2013-01-08 +================== + + * fix typo diff --git a/node_modules/component-events/Makefile b/node_modules/component-events/Makefile new file mode 100644 index 00000000..0f14dac3 --- /dev/null +++ b/node_modules/component-events/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components template.js + +.PHONY: clean diff --git a/node_modules/component-events/Readme.md b/node_modules/component-events/Readme.md new file mode 100644 index 00000000..f06acfa8 --- /dev/null +++ b/node_modules/component-events/Readme.md @@ -0,0 +1,112 @@ + +# events + + Higher level dom event management with direct and delegate event handling support. + + This component makes subscription management easy and unobtrusive since it does not muck with your view prototypes. Unbinding to "clean up" after your view is as simple as invoking `this.events.unbind()`, or more specific unbinds may be performed. + + It's design to work with a "host" object, typically a view, that provides callbacks, making callback management much less tedious than libraries like jQuery. + +## Installation + + $ component install component/events + +## Example + +```js +var events = require('events'); +var el = document.querySelector('.user'); + +var view = new UserView(el); + +function UserView(el) { + this.events = events(el, this); + this.events.bind('click .remove', 'remove'); + this.events.bind('click .hide', 'hide'); +} + +UserView.prototype.remove = function(){ + // remove the user + this.hide(); +}; + +UserView.prototype.hide = function(){ + // hide the view +}; + +UserView.prototype.destroy = function(){ + // clean up anything you need to + this.events.unbind(); +}; +``` + +## API + +### Events(el, obj) + + Initialize a new events manager targetting the + given element. Methods are delegated to `obj`. + +### Events#bind(event, [method]) + + Bind direct event handlers or delegates with `event` and + invoke `method` when the event occurs, passing the event object. + When `method` is not defined the `event` name prefixed with "on" is used. + + For example the following will invoke `onmousedown`, `onmousemove`, + and `onmouseup`: + +```js +events.bind('mousedown') +events.bind('mousemove') +events.bind('mouseup') +``` + + Alternatively you may specify the `method` name: + +```js +events.bind('click', 'toggleDisplay') +``` + + To use event delegation simply pass a selector after the + event name as shown here: + +```js +events.bind('click .remove', 'remove') +events.bind('click .close', 'hide') +``` + + You may bind to the same element with several events if necessary, + for example here perhaps `.remove()` does not manually invoke `.hide()`: + +```js +events.bind('click .remove', 'remove') +events.bind('click .remove', 'hide') +events.bind('click .close', 'hide') +``` + + Addition arguments are passed to the callee, which + is helpful for slight variations of a method, for + example sorting: + +```js +events.bind('click .sort-asc', 'sort', 'asc') +events.bind('click .sort-dsc', 'sort', 'dsc') +``` + +### Events.unbind([event], [method]) + + There are three flavours of unbinding -- you may unbind _all_ + event handlers, all specific to `event`, or all specific to + `event` and the given `method`. For example these are all valid: + +```js +events.unbind('click', 'remove') +events.unbind('click', 'hide') +events.unbind('click') +events.unbind() +``` + +## License + + MIT diff --git a/node_modules/component-events/component.json b/node_modules/component-events/component.json new file mode 100644 index 00000000..58efe56c --- /dev/null +++ b/node_modules/component-events/component.json @@ -0,0 +1,20 @@ +{ + "name": "events", + "repo": "component/events", + "description": "Higher level dom event management", + "version": "1.0.10", + "keywords": [ + "event", + "events", + "subscriptions" + ], + "dependencies": { + "component/event": "0.1.4", + "component/delegate": "0.2.4" + }, + "development": {}, + "license": "MIT", + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-events/examples/delegation.html b/node_modules/component-events/examples/delegation.html new file mode 100644 index 00000000..dd8a7814 --- /dev/null +++ b/node_modules/component-events/examples/delegation.html @@ -0,0 +1,45 @@ + + + Events + + + + + + + + + diff --git a/node_modules/component-events/examples/events.html b/node_modules/component-events/examples/events.html new file mode 100644 index 00000000..b63499c6 --- /dev/null +++ b/node_modules/component-events/examples/events.html @@ -0,0 +1,26 @@ + + + Events + + + + + + + + diff --git a/node_modules/component-events/examples/method.html b/node_modules/component-events/examples/method.html new file mode 100644 index 00000000..813a6af4 --- /dev/null +++ b/node_modules/component-events/examples/method.html @@ -0,0 +1,26 @@ + + + Events + + + + + + + + diff --git a/node_modules/component-events/index.js b/node_modules/component-events/index.js new file mode 100644 index 00000000..e505a52b --- /dev/null +++ b/node_modules/component-events/index.js @@ -0,0 +1,185 @@ + +/** + * Module dependencies. + */ + +try { + var events = require('event'); +} catch(err) { + var events = require('component-event'); +} + +try { + var delegate = require('delegate'); +} catch(err) { + var delegate = require('component-delegate'); +} + +/** + * Expose `Events`. + */ + +module.exports = Events; + +/** + * Initialize an `Events` with the given + * `el` object which events will be bound to, + * and the `obj` which will receive method calls. + * + * @param {Object} el + * @param {Object} obj + * @api public + */ + +function Events(el, obj) { + if (!(this instanceof Events)) return new Events(el, obj); + if (!el) throw new Error('element required'); + if (!obj) throw new Error('object required'); + this.el = el; + this.obj = obj; + this._events = {}; +} + +/** + * Subscription helper. + */ + +Events.prototype.sub = function(event, method, cb){ + this._events[event] = this._events[event] || {}; + this._events[event][method] = cb; +}; + +/** + * Bind to `event` with optional `method` name. + * When `method` is undefined it becomes `event` + * with the "on" prefix. + * + * Examples: + * + * Direct event handling: + * + * events.bind('click') // implies "onclick" + * events.bind('click', 'remove') + * events.bind('click', 'sort', 'asc') + * + * Delegated event handling: + * + * events.bind('click li > a') + * events.bind('click li > a', 'remove') + * events.bind('click a.sort-ascending', 'sort', 'asc') + * events.bind('click a.sort-descending', 'sort', 'desc') + * + * @param {String} event + * @param {String|function} [method] + * @return {Function} callback + * @api public + */ + +Events.prototype.bind = function(event, method){ + var e = parse(event); + var el = this.el; + var obj = this.obj; + var name = e.name; + var method = method || 'on' + name; + var args = [].slice.call(arguments, 2); + + // callback + function cb(){ + var a = [].slice.call(arguments).concat(args); + obj[method].apply(obj, a); + } + + // bind + if (e.selector) { + cb = delegate.bind(el, e.selector, name, cb); + } else { + events.bind(el, name, cb); + } + + // subscription for unbinding + this.sub(name, method, cb); + + return cb; +}; + +/** + * Unbind a single binding, all bindings for `event`, + * or all bindings within the manager. + * + * Examples: + * + * Unbind direct handlers: + * + * events.unbind('click', 'remove') + * events.unbind('click') + * events.unbind() + * + * Unbind delegate handlers: + * + * events.unbind('click', 'remove') + * events.unbind('click') + * events.unbind() + * + * @param {String|Function} [event] + * @param {String|Function} [method] + * @api public + */ + +Events.prototype.unbind = function(event, method){ + if (0 == arguments.length) return this.unbindAll(); + if (1 == arguments.length) return this.unbindAllOf(event); + + // no bindings for this event + var bindings = this._events[event]; + if (!bindings) return; + + // no bindings for this method + var cb = bindings[method]; + if (!cb) return; + + events.unbind(this.el, event, cb); +}; + +/** + * Unbind all events. + * + * @api private + */ + +Events.prototype.unbindAll = function(){ + for (var event in this._events) { + this.unbindAllOf(event); + } +}; + +/** + * Unbind all events for `event`. + * + * @param {String} event + * @api private + */ + +Events.prototype.unbindAllOf = function(event){ + var bindings = this._events[event]; + if (!bindings) return; + + for (var method in bindings) { + this.unbind(event, method); + } +}; + +/** + * Parse `event`. + * + * @param {String} event + * @return {Object} + * @api private + */ + +function parse(event) { + var parts = event.split(/ +/); + return { + name: parts.shift(), + selector: parts.join(' ') + } +} diff --git a/node_modules/component-events/package.json b/node_modules/component-events/package.json new file mode 100644 index 00000000..e2c8773b --- /dev/null +++ b/node_modules/component-events/package.json @@ -0,0 +1,21 @@ +{ + "name": "component-events", + "version": "1.0.10", + "dependencies": { + "component-event": "0.1.4", + "component-delegate": "0.2.4" + }, + "component": { + "scripts": { + "events/index.js": "index.js" + } + }, + "browser": { + "delegate": "component-delegate", + "event": "component-event" + }, + "repository": { + "type": "git", + "url": "https://github.com/component/events.git" + } +} diff --git a/node_modules/component-matches-selector/.npmignore b/node_modules/component-matches-selector/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/component-matches-selector/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/component-matches-selector/History.md b/node_modules/component-matches-selector/History.md new file mode 100644 index 00000000..c51e3fd7 --- /dev/null +++ b/node_modules/component-matches-selector/History.md @@ -0,0 +1,42 @@ + +0.1.7 / 2019-04-21 +================== +* using global-object to get `global.Element` so this code can be safely run inside of non-browser environments (#16, @antialias) + +0.1.6 / 2016-04-01 +================== + + * index: fall back to `require('component-query')` (#15, @ockham) + +0.1.5 / 2014-07-27 +================== + + * index: don't throw an Error when given falsey or non-Element nodes + +0.1.4 / 2014-05-27 +================== + + * force re-publish since something happened with npm + +0.1.3 / 2014-05-27 +================== + + * package: add "browser" field for browserify + +0.1.2 / 2014-02-10 +================== + + * package: pin "component-query" version + * package: add `package.json` file + * component: beautify "keywords" + +0.1.1 / 2013-10-15 +================== + + * use `query.all()` not `query()` + * use `proto.matches` + +0.1.0 / 2013-04-15 +================== + + * use component/query to support fallbacks diff --git a/node_modules/component-matches-selector/Makefile b/node_modules/component-matches-selector/Makefile new file mode 100644 index 00000000..0f14dac3 --- /dev/null +++ b/node_modules/component-matches-selector/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components template.js + +.PHONY: clean diff --git a/node_modules/component-matches-selector/Readme.md b/node_modules/component-matches-selector/Readme.md new file mode 100644 index 00000000..80fe03be --- /dev/null +++ b/node_modules/component-matches-selector/Readme.md @@ -0,0 +1,20 @@ + +# matches-selector + + Check if an element matches a given selector. + +## Installation + + $ component install component/matches-selector + +## Example + +```js +var matches = require('matches-selector'); +matches(el, 'ul li a'); +// => true +``` + +## License + + MIT diff --git a/node_modules/component-matches-selector/component.json b/node_modules/component-matches-selector/component.json new file mode 100644 index 00000000..8f4a49b9 --- /dev/null +++ b/node_modules/component-matches-selector/component.json @@ -0,0 +1,20 @@ +{ + "name": "matches-selector", + "repo": "component/matches-selector", + "description": "Check if an element matches a given selector", + "version": "0.1.7", + "keywords": [ + "match", + "element", + "selector" + ], + "dependencies": { + "component/query": "*" + }, + "development": { + "component/domify": "*" + }, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-matches-selector/index.js b/node_modules/component-matches-selector/index.js new file mode 100644 index 00000000..97ebe5d0 --- /dev/null +++ b/node_modules/component-matches-selector/index.js @@ -0,0 +1,51 @@ +/** + * Module dependencies. + */ + +try { + var query = require('query'); +} catch (err) { + var query = require('component-query'); +} + +/** + * Element prototype. + */ + +var Element = require('global-object').Element; +var proto = Element && Element.prototype || {}; + +/** + * Vendor function. + */ + +var vendor = proto.matches + || proto.webkitMatchesSelector + || proto.mozMatchesSelector + || proto.msMatchesSelector + || proto.oMatchesSelector; + +/** + * Expose `match()`. + */ + +module.exports = match; + +/** + * Match `el` to `selector`. + * + * @param {Element} el + * @param {String} selector + * @return {Boolean} + * @api public + */ + +function match(el, selector) { + if (!el || el.nodeType !== 1) return false; + if (vendor) return vendor.call(el, selector); + var nodes = query.all(selector, el.parentNode); + for (var i = 0; i < nodes.length; ++i) { + if (nodes[i] == el) return true; + } + return false; +} diff --git a/node_modules/component-matches-selector/package.json b/node_modules/component-matches-selector/package.json new file mode 100644 index 00000000..3f9589fd --- /dev/null +++ b/node_modules/component-matches-selector/package.json @@ -0,0 +1,22 @@ +{ + "name": "component-matches-selector", + "version": "0.1.7", + "description": "Check if an element matches a given selector", + "keywords": [ + "match", + "element", + "selector" + ], + "repository": { + "type": "git", + "url": "git://github.com/component/matches-selector.git" + }, + "dependencies": { + "component-query": "*", + "global-object": "^1.0.0" + }, + "browser": { + "query": "component-query" + }, + "license": "MIT" +} diff --git a/node_modules/component-matches-selector/test/index.html b/node_modules/component-matches-selector/test/index.html new file mode 100644 index 00000000..bd919395 --- /dev/null +++ b/node_modules/component-matches-selector/test/index.html @@ -0,0 +1,17 @@ + + + Mocha + + + + +
+ + + + + + + diff --git a/node_modules/component-matches-selector/test/mocha.css b/node_modules/component-matches-selector/test/mocha.css new file mode 100644 index 00000000..01bac1ab --- /dev/null +++ b/node_modules/component-matches-selector/test/mocha.css @@ -0,0 +1,199 @@ +@charset "UTF-8"; +body { + font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 60px 50px; +} + +#mocha ul, #mocha li { + margin: 0; + padding: 0; +} + +#mocha ul { + list-style: none; +} + +#mocha h1, #mocha h2 { + margin: 0; +} + +#mocha h1 { + margin-top: 15px; + font-size: 1em; + font-weight: 200; +} + +#mocha h1 a { + text-decoration: none; + color: inherit; +} + +#mocha h1 a:hover { + text-decoration: underline; +} + +#mocha .suite .suite h1 { + margin-top: 0; + font-size: .8em; +} + +#mocha h2 { + font-size: 12px; + font-weight: normal; + cursor: pointer; +} + +#mocha .suite { + margin-left: 15px; +} + +#mocha .test { + margin-left: 15px; +} + +#mocha .test:hover h2::after { + position: relative; + top: 0; + right: -10px; + content: '(view source)'; + font-size: 12px; + font-family: arial; + color: #888; +} + +#mocha .test.pending:hover h2::after { + content: '(pending)'; + font-family: arial; +} + +#mocha .test.pass.medium .duration { + background: #C09853; +} + +#mocha .test.pass.slow .duration { + background: #B94A48; +} + +#mocha .test.pass::before { + content: '✓'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #00d6b2; +} + +#mocha .test.pass .duration { + font-size: 9px; + margin-left: 5px; + padding: 2px 5px; + color: white; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +#mocha .test.pass.fast .duration { + display: none; +} + +#mocha .test.pending { + color: #0b97c4; +} + +#mocha .test.pending::before { + content: '◦'; + color: #0b97c4; +} + +#mocha .test.fail { + color: #c00; +} + +#mocha .test.fail pre { + color: black; +} + +#mocha .test.fail::before { + content: '✖'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #c00; +} + +#mocha .test pre.error { + color: #c00; +} + +#mocha .test pre { + display: inline-block; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + border-bottom-color: #ddd; + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px #eee; +} + +#report.pass .test.fail { + display: none; +} + +#report.fail .test.pass { + display: none; +} + +#error { + color: #c00; + font-size: 1.5 em; + font-weight: 100; + letter-spacing: 1px; +} + +#stats { + position: fixed; + top: 15px; + right: 10px; + font-size: 12px; + margin: 0; + color: #888; +} + +#stats .progress { + float: right; + padding-top: 0; +} + +#stats em { + color: black; +} + +#stats a { + text-decoration: none; + color: inherit; +} + +#stats a:hover { + border-bottom: 1px solid #eee; +} + +#stats li { + display: inline-block; + margin: 0 5px; + list-style: none; + padding-top: 11px; +} + +code .comment { color: #ddd } +code .init { color: #2F6FAD } +code .string { color: #5890AD } +code .keyword { color: #8A6343 } +code .number { color: #2F6FAD } diff --git a/node_modules/component-matches-selector/test/mocha.js b/node_modules/component-matches-selector/test/mocha.js new file mode 100644 index 00000000..1b148a1a --- /dev/null +++ b/node_modules/component-matches-selector/test/mocha.js @@ -0,0 +1,4699 @@ +;(function(){ + + +// CommonJS require() + +function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.charAt(0)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("browser/debug.js", function(module, exports, require){ + +module.exports = function(type){ + return function(){ + + } +}; +}); // module: browser/debug.js + +require.register("browser/diff.js", function(module, exports, require){ + +}); // module: browser/diff.js + +require.register("browser/events.js", function(module, exports, require){ + +/** + * Module exports. + */ + +exports.EventEmitter = EventEmitter; + +/** + * Check if `obj` is an array. + */ + +function isArray(obj) { + return '[object Array]' == {}.toString.call(obj); +} + +/** + * Event emitter constructor. + * + * @api public + */ + +function EventEmitter(){}; + +/** + * Adds a listener. + * + * @api public + */ + +EventEmitter.prototype.on = function (name, fn) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = fn; + } else if (isArray(this.$events[name])) { + this.$events[name].push(fn); + } else { + this.$events[name] = [this.$events[name], fn]; + } + + return this; +}; + +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +/** + * Adds a volatile listener. + * + * @api public + */ + +EventEmitter.prototype.once = function (name, fn) { + var self = this; + + function on () { + self.removeListener(name, on); + fn.apply(this, arguments); + }; + + on.listener = fn; + this.on(name, on); + + return this; +}; + +/** + * Removes a listener. + * + * @api public + */ + +EventEmitter.prototype.removeListener = function (name, fn) { + if (this.$events && this.$events[name]) { + var list = this.$events[name]; + + if (isArray(list)) { + var pos = -1; + + for (var i = 0, l = list.length; i < l; i++) { + if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { + pos = i; + break; + } + } + + if (pos < 0) { + return this; + } + + list.splice(pos, 1); + + if (!list.length) { + delete this.$events[name]; + } + } else if (list === fn || (list.listener && list.listener === fn)) { + delete this.$events[name]; + } + } + + return this; +}; + +/** + * Removes all listeners for an event. + * + * @api public + */ + +EventEmitter.prototype.removeAllListeners = function (name) { + if (name === undefined) { + this.$events = {}; + return this; + } + + if (this.$events && this.$events[name]) { + this.$events[name] = null; + } + + return this; +}; + +/** + * Gets all listeners for a certain event. + * + * @api public + */ + +EventEmitter.prototype.listeners = function (name) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = []; + } + + if (!isArray(this.$events[name])) { + this.$events[name] = [this.$events[name]]; + } + + return this.$events[name]; +}; + +/** + * Emits an event. + * + * @api public + */ + +EventEmitter.prototype.emit = function (name) { + if (!this.$events) { + return false; + } + + var handler = this.$events[name]; + + if (!handler) { + return false; + } + + var args = [].slice.call(arguments, 1); + + if ('function' == typeof handler) { + handler.apply(this, args); + } else if (isArray(handler)) { + var listeners = handler.slice(); + + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i].apply(this, args); + } + } else { + return false; + } + + return true; +}; +}); // module: browser/events.js + +require.register("browser/fs.js", function(module, exports, require){ + +}); // module: browser/fs.js + +require.register("browser/path.js", function(module, exports, require){ + +}); // module: browser/path.js + +require.register("browser/progress.js", function(module, exports, require){ + +/** + * Expose `Progress`. + */ + +module.exports = Progress; + +/** + * Initialize a new `Progress` indicator. + */ + +function Progress() { + this.percent = 0; + this.size(0); + this.fontSize(11); + this.font('helvetica, arial, sans-serif'); +} + +/** + * Set progress size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.size = function(n){ + this._size = n; + return this; +}; + +/** + * Set text to `str`. + * + * @param {String} str + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.text = function(str){ + this._text = str; + return this; +}; + +/** + * Set font size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.fontSize = function(n){ + this._fontSize = n; + return this; +}; + +/** + * Set font `family`. + * + * @param {String} family + * @return {Progress} for chaining + */ + +Progress.prototype.font = function(family){ + this._font = family; + return this; +}; + +/** + * Update percentage to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + */ + +Progress.prototype.update = function(n){ + this.percent = n; + return this; +}; + +/** + * Draw on `ctx`. + * + * @param {CanvasRenderingContext2d} ctx + * @return {Progress} for chaining + */ + +Progress.prototype.draw = function(ctx){ + var percent = Math.min(this.percent, 100) + , size = this._size + , half = size / 2 + , x = half + , y = half + , rad = half - 1 + , fontSize = this._fontSize; + + ctx.font = fontSize + 'px ' + this._font; + + var angle = Math.PI * 2 * (percent / 100); + ctx.clearRect(0, 0, size, size); + + // outer circle + ctx.strokeStyle = '#9f9f9f'; + ctx.beginPath(); + ctx.arc(x, y, rad, 0, angle, false); + ctx.stroke(); + + // inner circle + ctx.strokeStyle = '#eee'; + ctx.beginPath(); + ctx.arc(x, y, rad - 1, 0, angle, true); + ctx.stroke(); + + // text + var text = this._text || (percent | 0) + '%' + , w = ctx.measureText(text).width; + + ctx.fillText( + text + , x - w / 2 + 1 + , y + fontSize / 2 - 1); + + return this; +}; + +}); // module: browser/progress.js + +require.register("browser/tty.js", function(module, exports, require){ + +exports.isatty = function(){ + return true; +}; + +exports.getWindowSize = function(){ + return [window.innerHeight, window.innerWidth]; +}; +}); // module: browser/tty.js + +require.register("context.js", function(module, exports, require){ + +/** + * Expose `Context`. + */ + +module.exports = Context; + +/** + * Initialize a new `Context`. + * + * @api private + */ + +function Context(){} + +/** + * Set or get the context `Runnable` to `runnable`. + * + * @param {Runnable} runnable + * @return {Context} + * @api private + */ + +Context.prototype.runnable = function(runnable){ + if (0 == arguments.length) return this._runnable; + this.test = this._runnable = runnable; + return this; +}; + +/** + * Set test timeout `ms`. + * + * @param {Number} ms + * @return {Context} self + * @api private + */ + +Context.prototype.timeout = function(ms){ + this.runnable().timeout(ms); + return this; +}; + +/** + * Inspect the context void of `._runnable`. + * + * @return {String} + * @api private + */ + +Context.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_runnable' == key) return; + if ('test' == key) return; + return val; + }, 2); +}; + +}); // module: context.js + +require.register("hook.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Hook`. + */ + +module.exports = Hook; + +/** + * Initialize a new `Hook` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Hook(title, fn) { + Runnable.call(this, title, fn); + this.type = 'hook'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +Hook.prototype = new Runnable; +Hook.prototype.constructor = Hook; + + +/** + * Get or set the test `err`. + * + * @param {Error} err + * @return {Error} + * @api public + */ + +Hook.prototype.error = function(err){ + if (0 == arguments.length) { + var err = this._error; + this._error = null; + return err; + } + + this._error = err; +}; + + +}); // module: hook.js + +require.register("interfaces/bdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * BDD-style interface: + * + * describe('Array', function(){ + * describe('#indexOf()', function(){ + * it('should return -1 when not present', function(){ + * + * }); + * + * it('should return the index when present', function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.describe = context.context = function(title, fn){ + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + fn(); + suites.shift(); + return suite; + }; + + /** + * Pending describe. + */ + + context.xdescribe = + context.xcontext = + context.describe.skip = function(title, fn){ + var suite = Suite.create(suites[0], title); + suite.pending = true; + suites.unshift(suite); + fn(); + suites.shift(); + }; + + /** + * Exclusive suite. + */ + + context.describe.only = function(title, fn){ + var suite = context.describe(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.it = context.specify = function(title, fn){ + var suite = suites[0]; + if (suite.pending) var fn = null; + var test = new Test(title, fn); + suite.addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.it.only = function(title, fn){ + var test = context.it(title, fn); + mocha.grep(test.fullTitle()); + }; + + /** + * Pending test case. + */ + + context.xit = + context.xspecify = + context.it.skip = function(title){ + context.it(title); + }; + }); +}; + +}); // module: interfaces/bdd.js + +require.register("interfaces/exports.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * exports.Array = { + * '#indexOf()': { + * 'should return -1 when the value is not present': function(){ + * + * }, + * + * 'should return the correct index when the value is present': function(){ + * + * } + * } + * }; + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('require', visit); + + function visit(obj) { + var suite; + for (var key in obj) { + if ('function' == typeof obj[key]) { + var fn = obj[key]; + switch (key) { + case 'before': + suites[0].beforeAll(fn); + break; + case 'after': + suites[0].afterAll(fn); + break; + case 'beforeEach': + suites[0].beforeEach(fn); + break; + case 'afterEach': + suites[0].afterEach(fn); + break; + default: + suites[0].addTest(new Test(key, fn)); + } + } else { + var suite = Suite.create(suites[0], key); + suites.unshift(suite); + visit(obj[key]); + suites.shift(); + } + } + } +}; +}); // module: interfaces/exports.js + +require.register("interfaces/index.js", function(module, exports, require){ + +exports.bdd = require('./bdd'); +exports.tdd = require('./tdd'); +exports.qunit = require('./qunit'); +exports.exports = require('./exports'); + +}); // module: interfaces/index.js + +require.register("interfaces/qunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * QUnit-style interface: + * + * suite('Array'); + * + * test('#length', function(){ + * var arr = [1,2,3]; + * ok(arr.length == 3); + * }); + * + * test('#indexOf()', function(){ + * var arr = [1,2,3]; + * ok(arr.indexOf(1) == 0); + * ok(arr.indexOf(2) == 1); + * ok(arr.indexOf(3) == 2); + * }); + * + * suite('String'); + * + * test('#length', function(){ + * ok('foo'.length == 3); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title`. + */ + + context.suite = function(title){ + if (suites.length > 1) suites.shift(); + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(title, fn){ + suites[0].addTest(new Test(title, fn)); + }; + }); +}; + +}); // module: interfaces/qunit.js + +require.register("interfaces/tdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * suite('Array', function(){ + * suite('#indexOf()', function(){ + * suiteSetup(function(){ + * + * }); + * + * test('should return -1 when not present', function(){ + * + * }); + * + * test('should return the index when present', function(){ + * + * }); + * + * suiteTeardown(function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before each test case. + */ + + context.setup = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.teardown = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Execute before the suite. + */ + + context.suiteSetup = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after the suite. + */ + + context.suiteTeardown = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.suite = function(title, fn){ + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + fn(); + suites.shift(); + return suite; + }; + + /** + * Exclusive test-case. + */ + + context.suite.only = function(title, fn){ + var suite = context.suite(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(title, fn){ + var test = new Test(title, fn); + suites[0].addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.test.only = function(title, fn){ + var test = context.test(title, fn); + mocha.grep(test.fullTitle()); + }; + }); +}; + +}); // module: interfaces/tdd.js + +require.register("mocha.js", function(module, exports, require){ +/*! + * mocha + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var path = require('browser/path') + , utils = require('./utils'); + +/** + * Expose `Mocha`. + */ + +exports = module.exports = Mocha; + +/** + * Expose internals. + */ + +exports.utils = utils; +exports.interfaces = require('./interfaces'); +exports.reporters = require('./reporters'); +exports.Runnable = require('./runnable'); +exports.Context = require('./context'); +exports.Runner = require('./runner'); +exports.Suite = require('./suite'); +exports.Hook = require('./hook'); +exports.Test = require('./test'); + +/** + * Return image `name` path. + * + * @param {String} name + * @return {String} + * @api private + */ + +function image(name) { + return __dirname + '/../images/' + name + '.png'; +} + +/** + * Setup mocha with `options`. + * + * Options: + * + * - `ui` name "bdd", "tdd", "exports" etc + * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` + * - `globals` array of accepted globals + * - `timeout` timeout in milliseconds + * - `ignoreLeaks` ignore global leaks + * - `grep` string or regexp to filter tests with + * + * @param {Object} options + * @api public + */ + +function Mocha(options) { + options = options || {}; + this.files = []; + this.options = options; + this.grep(options.grep); + this.suite = new exports.Suite('', new exports.Context); + this.ui(options.ui); + this.reporter(options.reporter); + if (options.timeout) this.timeout(options.timeout); +} + +/** + * Add test `file`. + * + * @param {String} file + * @api public + */ + +Mocha.prototype.addFile = function(file){ + this.files.push(file); + return this; +}; + +/** + * Set reporter to `reporter`, defaults to "dot". + * + * @param {String|Function} reporter name of a reporter or a reporter constructor + * @api public + */ + +Mocha.prototype.reporter = function(reporter){ + if ('function' == typeof reporter) { + this._reporter = reporter; + } else { + reporter = reporter || 'dot'; + try { + this._reporter = require('./reporters/' + reporter); + } catch (err) { + this._reporter = require(reporter); + } + if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"'); + } + return this; +}; + +/** + * Set test UI `name`, defaults to "bdd". + * + * @param {String} bdd + * @api public + */ + +Mocha.prototype.ui = function(name){ + name = name || 'bdd'; + this._ui = exports.interfaces[name]; + if (!this._ui) throw new Error('invalid interface "' + name + '"'); + this._ui = this._ui(this.suite); + return this; +}; + +/** + * Load registered files. + * + * @api private + */ + +Mocha.prototype.loadFiles = function(fn){ + var self = this; + var suite = this.suite; + var pending = this.files.length; + this.files.forEach(function(file){ + file = path.resolve(file); + suite.emit('pre-require', global, file, self); + suite.emit('require', require(file), file, self); + suite.emit('post-require', global, file, self); + --pending || (fn && fn()); + }); +}; + +/** + * Enable growl support. + * + * @api private + */ + +Mocha.prototype._growl = function(runner, reporter) { + var notify = require('growl'); + + runner.on('end', function(){ + var stats = reporter.stats; + if (stats.failures) { + var msg = stats.failures + ' of ' + runner.total + ' tests failed'; + notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); + } else { + notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { + name: 'mocha' + , title: 'Passed' + , image: image('ok') + }); + } + }); +}; + +/** + * Add regexp to grep, if `re` is a string it is escaped. + * + * @param {RegExp|String} re + * @return {Mocha} + * @api public + */ + +Mocha.prototype.grep = function(re){ + this.options.grep = 'string' == typeof re + ? new RegExp(utils.escapeRegexp(re)) + : re; + return this; +}; + +/** + * Invert `.grep()` matches. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.invert = function(){ + this.options.invert = true; + return this; +}; + +/** + * Ignore global leaks. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.ignoreLeaks = function(){ + this.options.ignoreLeaks = true; + return this; +}; + +/** + * Enable growl support. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.growl = function(){ + this.options.growl = true; + return this; +}; + +/** + * Ignore `globals` array or string. + * + * @param {Array|String} globals + * @return {Mocha} + * @api public + */ + +Mocha.prototype.globals = function(globals){ + this.options.globals = (this.options.globals || []).concat(globals); + return this; +}; + +/** + * Set the timeout in milliseconds. + * + * @param {Number} timeout + * @return {Mocha} + * @api public + */ + +Mocha.prototype.timeout = function(timeout){ + this.suite.timeout(timeout); + return this; +}; + +/** + * Run tests and invoke `fn()` when complete. + * + * @param {Function} fn + * @return {Runner} + * @api public + */ + +Mocha.prototype.run = function(fn){ + this.loadFiles(); + var suite = this.suite; + var options = this.options; + var runner = new exports.Runner(suite); + var reporter = new this._reporter(runner); + runner.ignoreLeaks = options.ignoreLeaks; + if (options.grep) runner.grep(options.grep, options.invert); + if (options.globals) runner.globals(options.globals); + if (options.growl) this._growl(runner, reporter); + return runner.run(fn); +}; + +}); // module: mocha.js + +require.register("reporters/base.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var tty = require('browser/tty') + , diff = require('browser/diff'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Check if both stdio streams are associated with a tty. + */ + +var isatty = tty.isatty(1) && tty.isatty(2); + +/** + * Expose `Base`. + */ + +exports = module.exports = Base; + +/** + * Enable coloring by default. + */ + +exports.useColors = isatty; + +/** + * Default color map. + */ + +exports.colors = { + 'pass': 90 + , 'fail': 31 + , 'bright pass': 92 + , 'bright fail': 91 + , 'bright yellow': 93 + , 'pending': 36 + , 'suite': 0 + , 'error title': 0 + , 'error message': 31 + , 'error stack': 90 + , 'checkmark': 32 + , 'fast': 90 + , 'medium': 33 + , 'slow': 31 + , 'green': 32 + , 'light': 90 + , 'diff gutter': 90 + , 'diff added': 42 + , 'diff removed': 41 +}; + +/** + * Color `str` with the given `type`, + * allowing colors to be disabled, + * as well as user-defined color + * schemes. + * + * @param {String} type + * @param {String} str + * @return {String} + * @api private + */ + +var color = exports.color = function(type, str) { + if (!exports.useColors) return str; + return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; +}; + +/** + * Expose term window size, with some + * defaults for when stderr is not a tty. + */ + +exports.window = { + width: isatty + ? process.stdout.getWindowSize + ? process.stdout.getWindowSize(1)[0] + : tty.getWindowSize()[1] + : 75 +}; + +/** + * Expose some basic cursor interactions + * that are common among reporters. + */ + +exports.cursor = { + hide: function(){ + process.stdout.write('\u001b[?25l'); + }, + + show: function(){ + process.stdout.write('\u001b[?25h'); + }, + + deleteLine: function(){ + process.stdout.write('\u001b[2K'); + }, + + beginningOfLine: function(){ + process.stdout.write('\u001b[0G'); + }, + + CR: function(){ + exports.cursor.deleteLine(); + exports.cursor.beginningOfLine(); + } +}; + +/** + * A test is considered slow if it + * exceeds the following value in milliseconds. + */ + +exports.slow = 75; + +/** + * Outut the given `failures` as a list. + * + * @param {Array} failures + * @api public + */ + +exports.list = function(failures){ + console.error(); + failures.forEach(function(test, i){ + // format + var fmt = color('error title', ' %s) %s:\n') + + color('error message', ' %s') + + color('error stack', '\n%s\n'); + + // msg + var err = test.err + , message = err.message || '' + , stack = err.stack || message + , index = stack.indexOf(message) + message.length + , msg = stack.slice(0, index) + , actual = err.actual + , expected = err.expected; + + // actual / expected diff + if ('string' == typeof actual && 'string' == typeof expected) { + var len = Math.max(actual.length, expected.length); + + if (len < 20) msg = errorDiff(err, 'Chars'); + else msg = errorDiff(err, 'Words'); + + // linenos + var lines = msg.split('\n'); + if (lines.length > 4) { + var width = String(lines.length).length; + msg = lines.map(function(str, i){ + return pad(++i, width) + ' |' + ' ' + str; + }).join('\n'); + } + + // legend + msg = '\n' + + color('diff removed', 'actual') + + ' ' + + color('diff added', 'expected') + + '\n\n' + + msg + + '\n'; + + // indent + msg = msg.replace(/^/gm, ' '); + + fmt = color('error title', ' %s) %s:\n%s') + + color('error stack', '\n%s\n'); + } + + // indent stack trace without msg + stack = stack.slice(index ? index + 1 : index) + .replace(/^/gm, ' '); + + console.error(fmt, (i + 1), test.fullTitle(), msg, stack); + }); +}; + +/** + * Initialize a new `Base` reporter. + * + * All other reporters generally + * inherit from this reporter, providing + * stats such as test duration, number + * of tests passed / failed etc. + * + * @param {Runner} runner + * @api public + */ + +function Base(runner) { + var self = this + , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } + , failures = this.failures = []; + + if (!runner) return; + this.runner = runner; + + runner.on('start', function(){ + stats.start = new Date; + }); + + runner.on('suite', function(suite){ + stats.suites = stats.suites || 0; + suite.root || stats.suites++; + }); + + runner.on('test end', function(test){ + stats.tests = stats.tests || 0; + stats.tests++; + }); + + runner.on('pass', function(test){ + stats.passes = stats.passes || 0; + + var medium = exports.slow / 2; + test.speed = test.duration > exports.slow + ? 'slow' + : test.duration > medium + ? 'medium' + : 'fast'; + + stats.passes++; + }); + + runner.on('fail', function(test, err){ + stats.failures = stats.failures || 0; + stats.failures++; + test.err = err; + failures.push(test); + }); + + runner.on('end', function(){ + stats.end = new Date; + stats.duration = new Date - stats.start; + }); + + runner.on('pending', function(){ + stats.pending++; + }); +} + +/** + * Output common epilogue used by many of + * the bundled reporters. + * + * @api public + */ + +Base.prototype.epilogue = function(){ + var stats = this.stats + , fmt + , tests; + + console.log(); + + function pluralize(n) { + return 1 == n ? 'test' : 'tests'; + } + + // failure + if (stats.failures) { + fmt = color('bright fail', ' ✖') + + color('fail', ' %d of %d %s failed') + + color('light', ':') + + console.error(fmt, + stats.failures, + this.runner.total, + pluralize(this.runner.total)); + + Base.list(this.failures); + console.error(); + return; + } + + // pass + fmt = color('bright pass', ' ✔') + + color('green', ' %d %s complete') + + color('light', ' (%dms)'); + + console.log(fmt, + stats.tests || 0, + pluralize(stats.tests), + stats.duration); + + // pending + if (stats.pending) { + fmt = color('pending', ' •') + + color('pending', ' %d %s pending'); + + console.log(fmt, stats.pending, pluralize(stats.pending)); + } + + console.log(); +}; + +/** + * Pad the given `str` to `len`. + * + * @param {String} str + * @param {String} len + * @return {String} + * @api private + */ + +function pad(str, len) { + str = String(str); + return Array(len - str.length + 1).join(' ') + str; +} + +/** + * Return a character diff for `err`. + * + * @param {Error} err + * @return {String} + * @api private + */ + +function errorDiff(err, type) { + return diff['diff' + type](err.actual, err.expected).map(function(str){ + if (/^(\n+)$/.test(str.value)) str.value = Array(++RegExp.$1.length).join(''); + if (str.added) return colorLines('diff added', str.value); + if (str.removed) return colorLines('diff removed', str.value); + return str.value; + }).join(''); +} + +/** + * Color lines for `str`, using the color `name`. + * + * @param {String} name + * @param {String} str + * @return {String} + * @api private + */ + +function colorLines(name, str) { + return str.split('\n').map(function(str){ + return color(name, str); + }).join('\n'); +} + +}); // module: reporters/base.js + +require.register("reporters/doc.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Doc`. + */ + +exports = module.exports = Doc; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Doc(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , indents = 2; + + function indent() { + return Array(indents).join(' '); + } + + runner.on('suite', function(suite){ + if (suite.root) return; + ++indents; + console.log('%s
', indent()); + ++indents; + console.log('%s

%s

', indent(), suite.title); + console.log('%s
', indent()); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + console.log('%s
', indent()); + --indents; + console.log('%s
', indent()); + --indents; + }); + + runner.on('pass', function(test){ + console.log('%s
%s
', indent(), test.title); + var code = utils.escape(utils.clean(test.fn.toString())); + console.log('%s
%s
', indent(), code); + }); +} + +}); // module: reporters/doc.js + +require.register("reporters/dot.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = Dot; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Dot(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , c = '․' + , n = 0; + + runner.on('start', function(){ + process.stdout.write('\n '); + }); + + runner.on('pending', function(test){ + process.stdout.write(color('pending', c)); + }); + + runner.on('pass', function(test){ + if (++n % width == 0) process.stdout.write('\n '); + if ('slow' == test.speed) { + process.stdout.write(color('bright yellow', c)); + } else { + process.stdout.write(color(test.speed, c)); + } + }); + + runner.on('fail', function(test, err){ + if (++n % width == 0) process.stdout.write('\n '); + process.stdout.write(color('fail', c)); + }); + + runner.on('end', function(){ + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Dot.prototype = new Base; +Dot.prototype.constructor = Dot; + +}); // module: reporters/dot.js + +require.register("reporters/html-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var JSONCov = require('./json-cov') + , fs = require('browser/fs'); + +/** + * Expose `HTMLCov`. + */ + +exports = module.exports = HTMLCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTMLCov(runner) { + var jade = require('jade') + , file = __dirname + '/templates/coverage.jade' + , str = fs.readFileSync(file, 'utf8') + , fn = jade.compile(str, { filename: file }) + , self = this; + + JSONCov.call(this, runner, false); + + runner.on('end', function(){ + process.stdout.write(fn({ + cov: self.cov + , coverageClass: coverageClass + })); + }); +} + +/** + * Return coverage class for `n`. + * + * @return {String} + * @api private + */ + +function coverageClass(n) { + if (n >= 75) return 'high'; + if (n >= 50) return 'medium'; + if (n >= 25) return 'low'; + return 'terrible'; +} +}); // module: reporters/html-cov.js + +require.register("reporters/html.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , Progress = require('../browser/progress') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `Doc`. + */ + +exports = module.exports = HTML; + +/** + * Stats template. + */ + +var statsTemplate = ''; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTML(runner, root) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , stat = fragment(statsTemplate) + , items = stat.getElementsByTagName('li') + , passes = items[1].getElementsByTagName('em')[0] + , passesLink = items[1].getElementsByTagName('a')[0] + , failures = items[2].getElementsByTagName('em')[0] + , failuresLink = items[2].getElementsByTagName('a')[0] + , duration = items[3].getElementsByTagName('em')[0] + , canvas = stat.getElementsByTagName('canvas')[0] + , report = fragment('
    ') + , stack = [report] + , progress + , ctx + + root = root || document.getElementById('mocha'); + + if (canvas.getContext) { + var ratio = window.devicePixelRatio || 1; + canvas.style.width = canvas.width; + canvas.style.height = canvas.height; + canvas.width *= ratio; + canvas.height *= ratio; + ctx = canvas.getContext('2d'); + ctx.scale(ratio, ratio); + progress = new Progress; + } + + if (!root) return error('#mocha div missing, add it to your document'); + + // pass toggle + on(passesLink, 'click', function () { + var className = /pass/.test(report.className) ? '' : ' pass'; + report.className = report.className.replace(/fail|pass/g, '') + className; + }); + + // failure toggle + on(failuresLink, 'click', function () { + var className = /fail/.test(report.className) ? '' : ' fail'; + report.className = report.className.replace(/fail|pass/g, '') + className; + }); + + root.appendChild(stat); + root.appendChild(report); + + if (progress) progress.size(40); + + runner.on('suite', function(suite){ + if (suite.root) return; + + // suite + var url = '?grep=' + encodeURIComponent(suite.fullTitle()); + var el = fragment('
  • %s

  • ', url, escape(suite.title)); + + // container + stack[0].appendChild(el); + stack.unshift(document.createElement('ul')); + el.appendChild(stack[0]); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + stack.shift(); + }); + + runner.on('fail', function(test, err){ + if ('hook' == test.type || err.uncaught) runner.emit('test end', test); + }); + + runner.on('test end', function(test){ + window.scrollTo(0, document.body.scrollHeight); + + // TODO: add to stats + var percent = stats.tests / total * 100 | 0; + if (progress) progress.update(percent).draw(ctx); + + // update stats + var ms = new Date - stats.start; + text(passes, stats.passes); + text(failures, stats.failures); + text(duration, (ms / 1000).toFixed(2)); + + // test + if ('passed' == test.state) { + var el = fragment('
  • %e%ems

  • ', test.speed, test.title, test.duration); + } else if (test.pending) { + var el = fragment('
  • %e

  • ', test.title); + } else { + var el = fragment('
  • %e

  • ', test.title); + var str = test.err.stack || test.err.toString(); + + // FF / Opera do not add the message + if (!~str.indexOf(test.err.message)) { + str = test.err.message + '\n' + str; + } + + // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we + // check for the result of the stringifying. + if ('[object Error]' == str) str = test.err.message; + + // Safari doesn't give you a stack. Let's at least provide a source line. + if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { + str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; + } + + el.appendChild(fragment('
    %e
    ', str)); + } + + // toggle code + // TODO: defer + if (!test.pending) { + var h2 = el.getElementsByTagName('h2')[0]; + + on(h2, 'click', function(){ + pre.style.display = 'none' == pre.style.display + ? 'inline-block' + : 'none'; + }); + + var pre = fragment('
    %e
    ', utils.clean(test.fn.toString())); + el.appendChild(pre); + pre.style.display = 'none'; + } + + stack[0].appendChild(el); + }); +} + +/** + * Display error `msg`. + */ + +function error(msg) { + document.body.appendChild(fragment('
    %s
    ', msg)); +} + +/** + * Return a DOM fragment from `html`. + */ + +function fragment(html) { + var args = arguments + , div = document.createElement('div') + , i = 1; + + div.innerHTML = html.replace(/%([se])/g, function(_, type){ + switch (type) { + case 's': return String(args[i++]); + case 'e': return escape(args[i++]); + } + }); + + return div.firstChild; +} + +/** + * Set `el` text to `str`. + */ + +function text(el, str) { + if (el.textContent) { + el.textContent = str; + } else { + el.innerText = str; + } +} + +/** + * Listen on `event` with callback `fn`. + */ + +function on(el, event, fn) { + if (el.addEventListener) { + el.addEventListener(event, fn, false); + } else { + el.attachEvent('on' + event, fn); + } +} + +}); // module: reporters/html.js + +require.register("reporters/index.js", function(module, exports, require){ + +exports.Base = require('./base'); +exports.Dot = require('./dot'); +exports.Doc = require('./doc'); +exports.TAP = require('./tap'); +exports.JSON = require('./json'); +exports.HTML = require('./html'); +exports.List = require('./list'); +exports.Min = require('./min'); +exports.Spec = require('./spec'); +exports.Nyan = require('./nyan'); +exports.XUnit = require('./xunit'); +exports.Markdown = require('./markdown'); +exports.Progress = require('./progress'); +exports.Landing = require('./landing'); +exports.JSONCov = require('./json-cov'); +exports.HTMLCov = require('./html-cov'); +exports.JSONStream = require('./json-stream'); +exports.Teamcity = require('./teamcity'); + +}); // module: reporters/index.js + +require.register("reporters/json-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `JSONCov`. + */ + +exports = module.exports = JSONCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @param {Boolean} output + * @api public + */ + +function JSONCov(runner, output) { + var self = this + , output = 1 == arguments.length ? true : output; + + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var cov = global._$jscoverage || {}; + var result = self.cov = map(cov); + result.stats = self.stats; + result.tests = tests.map(clean); + result.failures = failures.map(clean); + result.passes = passes.map(clean); + if (!output) return; + process.stdout.write(JSON.stringify(result, null, 2 )); + }); +} + +/** + * Map jscoverage data to a JSON structure + * suitable for reporting. + * + * @param {Object} cov + * @return {Object} + * @api private + */ + +function map(cov) { + var ret = { + instrumentation: 'node-jscoverage' + , sloc: 0 + , hits: 0 + , misses: 0 + , coverage: 0 + , files: [] + }; + + for (var filename in cov) { + var data = coverage(filename, cov[filename]); + ret.files.push(data); + ret.hits += data.hits; + ret.misses += data.misses; + ret.sloc += data.sloc; + } + + if (ret.sloc > 0) { + ret.coverage = (ret.hits / ret.sloc) * 100; + } + + return ret; +}; + +/** + * Map jscoverage data for a single source file + * to a JSON structure suitable for reporting. + * + * @param {String} filename name of the source file + * @param {Object} data jscoverage coverage data + * @return {Object} + * @api private + */ + +function coverage(filename, data) { + var ret = { + filename: filename, + coverage: 0, + hits: 0, + misses: 0, + sloc: 0, + source: {} + }; + + data.source.forEach(function(line, num){ + num++; + + if (data[num] === 0) { + ret.misses++; + ret.sloc++; + } else if (data[num] !== undefined) { + ret.hits++; + ret.sloc++; + } + + ret.source[num] = { + source: line + , coverage: data[num] === undefined + ? '' + : data[num] + }; + }); + + ret.coverage = ret.hits / ret.sloc * 100; + + return ret; +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} + +}); // module: reporters/json-cov.js + +require.register("reporters/json-stream.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total; + + runner.on('start', function(){ + console.log(JSON.stringify(['start', { total: total }])); + }); + + runner.on('pass', function(test){ + console.log(JSON.stringify(['pass', clean(test)])); + }); + + runner.on('fail', function(test, err){ + console.log(JSON.stringify(['fail', clean(test)])); + }); + + runner.on('end', function(){ + process.stdout.write(JSON.stringify(['end', self.stats])); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json-stream.js + +require.register("reporters/json.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `JSON`. + */ + +exports = module.exports = JSONReporter; + +/** + * Initialize a new `JSON` reporter. + * + * @param {Runner} runner + * @api public + */ + +function JSONReporter(runner) { + var self = this; + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var obj = { + stats: self.stats + , tests: tests.map(clean) + , failures: failures.map(clean) + , passes: passes.map(clean) + }; + + process.stdout.write(JSON.stringify(obj, null, 2)); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json.js + +require.register("reporters/landing.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Landing`. + */ + +exports = module.exports = Landing; + +/** + * Airplane color. + */ + +Base.colors.plane = 0; + +/** + * Airplane crash color. + */ + +Base.colors['plane crash'] = 31; + +/** + * Runway color. + */ + +Base.colors.runway = 90; + +/** + * Initialize a new `Landing` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Landing(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , total = runner.total + , stream = process.stdout + , plane = color('plane', '✈') + , crashed = -1 + , n = 0; + + function runway() { + var buf = Array(width).join('-'); + return ' ' + color('runway', buf); + } + + runner.on('start', function(){ + stream.write('\n '); + cursor.hide(); + }); + + runner.on('test end', function(test){ + // check if the plane crashed + var col = -1 == crashed + ? width * ++n / total | 0 + : crashed; + + // show the crash + if ('failed' == test.state) { + plane = color('plane crash', '✈'); + crashed = col; + } + + // render landing strip + stream.write('\u001b[4F\n\n'); + stream.write(runway()); + stream.write('\n '); + stream.write(color('runway', Array(col).join('⋅'))); + stream.write(plane) + stream.write(color('runway', Array(width - col).join('⋅') + '\n')); + stream.write(runway()); + stream.write('\u001b[0m'); + }); + + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Landing.prototype = new Base; +Landing.prototype.constructor = Landing; + +}); // module: reporters/landing.js + +require.register("reporters/list.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , n = 0; + + runner.on('start', function(){ + console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = color('checkmark', ' -') + + color('pending', ' %s'); + console.log(fmt, test.fullTitle()); + }); + + runner.on('pass', function(test){ + var fmt = color('checkmark', ' ✓') + + color('pass', ' %s: ') + + color(test.speed, '%dms'); + cursor.CR(); + console.log(fmt, test.fullTitle(), test.duration); + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +List.prototype = new Base; +List.prototype.constructor = List; + + +}); // module: reporters/list.js + +require.register("reporters/markdown.js", function(module, exports, require){ +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Markdown`. + */ + +exports = module.exports = Markdown; + +/** + * Initialize a new `Markdown` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Markdown(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , level = 0 + , buf = ''; + + function title(str) { + return Array(level).join('#') + ' ' + str; + } + + function indent() { + return Array(level).join(' '); + } + + function mapTOC(suite, obj) { + var ret = obj; + obj = obj[suite.title] = obj[suite.title] || { suite: suite }; + suite.suites.forEach(function(suite){ + mapTOC(suite, obj); + }); + return ret; + } + + function stringifyTOC(obj, level) { + ++level; + var buf = ''; + var link; + for (var key in obj) { + if ('suite' == key) continue; + if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; + if (key) buf += Array(level).join(' ') + link; + buf += stringifyTOC(obj[key], level); + } + --level; + return buf; + } + + function generateTOC(suite) { + var obj = mapTOC(suite, {}); + return stringifyTOC(obj, 0); + } + + generateTOC(runner.suite); + + runner.on('suite', function(suite){ + ++level; + var slug = utils.slug(suite.fullTitle()); + buf += '' + '\n'; + buf += title(suite.title) + '\n'; + }); + + runner.on('suite end', function(suite){ + --level; + }); + + runner.on('pass', function(test){ + var code = utils.clean(test.fn.toString()); + buf += test.title + '.\n'; + buf += '\n```js\n'; + buf += code + '\n'; + buf += '```\n\n'; + }); + + runner.on('end', function(){ + process.stdout.write('# TOC\n'); + process.stdout.write(generateTOC(runner.suite)); + process.stdout.write(buf); + }); +} +}); // module: reporters/markdown.js + +require.register("reporters/min.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Min`. + */ + +exports = module.exports = Min; + +/** + * Initialize a new `Min` minimal test reporter (best used with --watch). + * + * @param {Runner} runner + * @api public + */ + +function Min(runner) { + Base.call(this, runner); + + runner.on('start', function(){ + // clear screen + process.stdout.write('\u001b[2J'); + // set cursor position + process.stdout.write('\u001b[1;3H'); + }); + + runner.on('end', this.epilogue.bind(this)); +} + +/** + * Inherit from `Base.prototype`. + */ + +Min.prototype = new Base; +Min.prototype.constructor = Min; + +}); // module: reporters/min.js + +require.register("reporters/nyan.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = NyanCat; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function NyanCat(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , rainbowColors = this.rainbowColors = self.generateColors() + , colorIndex = this.colorIndex = 0 + , numerOfLines = this.numberOfLines = 4 + , trajectories = this.trajectories = [[], [], [], []] + , nyanCatWidth = this.nyanCatWidth = 11 + , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) + , scoreboardWidth = this.scoreboardWidth = 5 + , tick = this.tick = 0 + , n = 0; + + runner.on('start', function(){ + Base.cursor.hide(); + self.draw('start'); + }); + + runner.on('pending', function(test){ + self.draw('pending'); + }); + + runner.on('pass', function(test){ + self.draw('pass'); + }); + + runner.on('fail', function(test, err){ + self.draw('fail'); + }); + + runner.on('end', function(){ + Base.cursor.show(); + for (var i = 0; i < self.numberOfLines; i++) write('\n'); + self.epilogue(); + }); +} + +/** + * Draw the nyan cat with runner `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.draw = function(status){ + this.appendRainbow(); + this.drawScoreboard(); + this.drawRainbow(); + this.drawNyanCat(status); + this.tick = !this.tick; +}; + +/** + * Draw the "scoreboard" showing the number + * of passes, failures and pending tests. + * + * @api private + */ + +NyanCat.prototype.drawScoreboard = function(){ + var stats = this.stats; + var colors = Base.colors; + + function draw(color, n) { + write(' '); + write('\u001b[' + color + 'm' + n + '\u001b[0m'); + write('\n'); + } + + draw(colors.green, stats.passes); + draw(colors.fail, stats.failures); + draw(colors.pending, stats.pending); + write('\n'); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Append the rainbow. + * + * @api private + */ + +NyanCat.prototype.appendRainbow = function(){ + var segment = this.tick ? '_' : '-'; + var rainbowified = this.rainbowify(segment); + + for (var index = 0; index < this.numberOfLines; index++) { + var trajectory = this.trajectories[index]; + if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); + trajectory.push(rainbowified); + } +}; + +/** + * Draw the rainbow. + * + * @api private + */ + +NyanCat.prototype.drawRainbow = function(){ + var self = this; + + this.trajectories.forEach(function(line, index) { + write('\u001b[' + self.scoreboardWidth + 'C'); + write(line.join('')); + write('\n'); + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Draw the nyan cat with `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.drawNyanCat = function(status) { + var self = this; + var startWidth = this.scoreboardWidth + this.trajectories[0].length; + + [0, 1, 2, 3].forEach(function(index) { + write('\u001b[' + startWidth + 'C'); + + switch (index) { + case 0: + write('_,------,'); + write('\n'); + break; + case 1: + var padding = self.tick ? ' ' : ' '; + write('_|' + padding + '/\\_/\\ '); + write('\n'); + break; + case 2: + var padding = self.tick ? '_' : '__'; + var tail = self.tick ? '~' : '^'; + var face; + switch (status) { + case 'pass': + face = '( ^ .^)'; + break; + case 'fail': + face = '( o .o)'; + break; + default: + face = '( - .-)'; + } + write(tail + '|' + padding + face + ' '); + write('\n'); + break; + case 3: + var padding = self.tick ? ' ' : ' '; + write(padding + '"" "" '); + write('\n'); + break; + } + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Move cursor up `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorUp = function(n) { + write('\u001b[' + n + 'A'); +}; + +/** + * Move cursor down `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorDown = function(n) { + write('\u001b[' + n + 'B'); +}; + +/** + * Generate rainbow colors. + * + * @return {Array} + * @api private + */ + +NyanCat.prototype.generateColors = function(){ + var colors = []; + + for (var i = 0; i < (6 * 7); i++) { + var pi3 = Math.floor(Math.PI / 3); + var n = (i * (1.0 / 6)); + var r = Math.floor(3 * Math.sin(n) + 3); + var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); + var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); + colors.push(36 * r + 6 * g + b + 16); + } + + return colors; +}; + +/** + * Apply rainbow to the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +NyanCat.prototype.rainbowify = function(str){ + var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; + this.colorIndex += 1; + return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; +}; + +/** + * Stdout helper. + */ + +function write(string) { + process.stdout.write(string); +} + +/** + * Inherit from `Base.prototype`. + */ + +NyanCat.prototype = new Base; +NyanCat.prototype.constructor = NyanCat; + + +}); // module: reporters/nyan.js + +require.register("reporters/progress.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Progress`. + */ + +exports = module.exports = Progress; + +/** + * General progress bar color. + */ + +Base.colors.progress = 90; + +/** + * Initialize a new `Progress` bar test reporter. + * + * @param {Runner} runner + * @param {Object} options + * @api public + */ + +function Progress(runner, options) { + Base.call(this, runner); + + var self = this + , options = options || {} + , stats = this.stats + , width = Base.window.width * .50 | 0 + , total = runner.total + , complete = 0 + , max = Math.max; + + // default chars + options.open = options.open || '['; + options.complete = options.complete || '▬'; + options.incomplete = options.incomplete || '⋅'; + options.close = options.close || ']'; + options.verbose = false; + + // tests started + runner.on('start', function(){ + console.log(); + cursor.hide(); + }); + + // tests complete + runner.on('test end', function(){ + complete++; + var incomplete = total - complete + , percent = complete / total + , n = width * percent | 0 + , i = width - n; + + cursor.CR(); + process.stdout.write('\u001b[J'); + process.stdout.write(color('progress', ' ' + options.open)); + process.stdout.write(Array(n).join(options.complete)); + process.stdout.write(Array(i).join(options.incomplete)); + process.stdout.write(color('progress', options.close)); + if (options.verbose) { + process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); + } + }); + + // tests are complete, output some stats + // and the failures if any + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Progress.prototype = new Base; +Progress.prototype.constructor = Progress; + + +}); // module: reporters/progress.js + +require.register("reporters/spec.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Spec`. + */ + +exports = module.exports = Spec; + +/** + * Initialize a new `Spec` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Spec(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , indents = 0 + , n = 0; + + function indent() { + return Array(indents).join(' ') + } + + runner.on('start', function(){ + console.log(); + }); + + runner.on('suite', function(suite){ + ++indents; + console.log(color('suite', '%s%s'), indent(), suite.title); + }); + + runner.on('suite end', function(suite){ + --indents; + if (1 == indents) console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = indent() + color('pending', ' - %s'); + console.log(fmt, test.title); + }); + + runner.on('pass', function(test){ + if ('fast' == test.speed) { + var fmt = indent() + + color('checkmark', ' ✓') + + color('pass', ' %s '); + cursor.CR(); + console.log(fmt, test.title); + } else { + var fmt = indent() + + color('checkmark', ' ✓') + + color('pass', ' %s ') + + color(test.speed, '(%dms)'); + cursor.CR(); + console.log(fmt, test.title, test.duration); + } + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +Spec.prototype = new Base; +Spec.prototype.constructor = Spec; + + +}); // module: reporters/spec.js + +require.register("reporters/tap.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `TAP`. + */ + +exports = module.exports = TAP; + +/** + * Initialize a new `TAP` reporter. + * + * @param {Runner} runner + * @api public + */ + +function TAP(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , n = 1; + + runner.on('start', function(){ + console.log('%d..%d', 1, total); + }); + + runner.on('test end', function(){ + ++n; + }); + + runner.on('pending', function(test){ + console.log('ok %d %s # SKIP -', n, title(test)); + }); + + runner.on('pass', function(test){ + console.log('ok %d %s', n, title(test)); + }); + + runner.on('fail', function(test, err){ + console.log('not ok %d %s', n, title(test)); + console.log(err.stack.replace(/^/gm, ' ')); + }); +} + +/** + * Return a TAP-safe title of `test` + * + * @param {Object} test + * @return {String} + * @api private + */ + +function title(test) { + return test.fullTitle().replace(/#/g, ''); +} + +}); // module: reporters/tap.js + +require.register("reporters/teamcity.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Teamcity`. + */ + +exports = module.exports = Teamcity; + +/** + * Initialize a new `Teamcity` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Teamcity(runner) { + Base.call(this, runner); + var stats = this.stats; + + runner.on('start', function() { + console.log("##teamcity[testSuiteStarted name='mocha.suite']"); + }); + + runner.on('test', function(test) { + console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); + }); + + runner.on('fail', function(test, err) { + console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); + }); + + runner.on('pending', function(test) { + console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); + }); + + runner.on('test end', function(test) { + console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); + }); + + runner.on('end', function() { + console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); + }); +} + +/** + * Escape the given `str`. + */ + +function escape(str) { + return str + .replace(/\|/g, "||") + .replace(/\n/g, "|n") + .replace(/\r/g, "|r") + .replace(/\[/g, "|[") + .replace(/\]/g, "|]") + .replace(/\u0085/g, "|x") + .replace(/\u2028/g, "|l") + .replace(/\u2029/g, "|p") + .replace(/'/g, "|'"); +} + +}); // module: reporters/teamcity.js + +require.register("reporters/xunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `XUnit`. + */ + +exports = module.exports = XUnit; + +/** + * Initialize a new `XUnit` reporter. + * + * @param {Runner} runner + * @api public + */ + +function XUnit(runner) { + Base.call(this, runner); + var stats = this.stats + , tests = [] + , self = this; + + runner.on('pass', function(test){ + tests.push(test); + }); + + runner.on('fail', function(test){ + tests.push(test); + }); + + runner.on('end', function(){ + console.log(tag('testsuite', { + name: 'Mocha Tests' + , tests: stats.tests + , failures: stats.failures + , errors: stats.failures + , skip: stats.tests - stats.failures - stats.passes + , timestamp: (new Date).toUTCString() + , time: stats.duration / 1000 + }, false)); + + tests.forEach(test); + console.log(''); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +XUnit.prototype = new Base; +XUnit.prototype.constructor = XUnit; + + +/** + * Output tag for the given `test.` + */ + +function test(test) { + var attrs = { + classname: test.parent.fullTitle() + , name: test.title + , time: test.duration / 1000 + }; + + if ('failed' == test.state) { + var err = test.err; + attrs.message = escape(err.message); + console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); + } else if (test.pending) { + console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); + } else { + console.log(tag('testcase', attrs, true) ); + } +} + +/** + * HTML tag helper. + */ + +function tag(name, attrs, close, content) { + var end = close ? '/>' : '>' + , pairs = [] + , tag; + + for (var key in attrs) { + pairs.push(key + '="' + escape(attrs[key]) + '"'); + } + + tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; + if (content) tag += content + ''; +} + +}); // module: reporters/xunit.js + +require.register("runnable.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runnable'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `Runnable`. + */ + +module.exports = Runnable; + +/** + * Initialize a new `Runnable` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Runnable(title, fn) { + this.title = title; + this.fn = fn; + this.async = fn && fn.length; + this.sync = ! this.async; + this._timeout = 2000; + this.timedOut = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Runnable.prototype = new EventEmitter; +Runnable.prototype.constructor = Runnable; + + +/** + * Set & get timeout `ms`. + * + * @param {Number} ms + * @return {Runnable|Number} ms or self + * @api private + */ + +Runnable.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + debug('timeout %d', ms); + this._timeout = ms; + if (this.timer) this.resetTimeout(); + return this; +}; + +/** + * Return the full title generated by recursively + * concatenating the parent's full title. + * + * @return {String} + * @api public + */ + +Runnable.prototype.fullTitle = function(){ + return this.parent.fullTitle() + ' ' + this.title; +}; + +/** + * Clear the timeout. + * + * @api private + */ + +Runnable.prototype.clearTimeout = function(){ + clearTimeout(this.timer); +}; + +/** + * Inspect the runnable void of private properties. + * + * @return {String} + * @api private + */ + +Runnable.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_' == key[0]) return; + if ('parent' == key) return '#'; + if ('ctx' == key) return '#'; + return val; + }, 2); +}; + +/** + * Reset the timeout. + * + * @api private + */ + +Runnable.prototype.resetTimeout = function(){ + var self = this + , ms = this.timeout(); + + this.clearTimeout(); + if (ms) { + this.timer = setTimeout(function(){ + self.callback(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } +}; + +/** + * Run the test and invoke `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runnable.prototype.run = function(fn){ + var self = this + , ms = this.timeout() + , start = new Date + , ctx = this.ctx + , finished + , emitted; + + if (ctx) ctx.runnable(this); + + // timeout + if (this.async) { + if (ms) { + this.timer = setTimeout(function(){ + done(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } + } + + // called multiple times + function multiple(err) { + if (emitted) return; + emitted = true; + self.emit('error', err || new Error('done() called multiple times')); + } + + // finished + function done(err) { + if (self.timedOut) return; + if (finished) return multiple(err); + self.clearTimeout(); + self.duration = new Date - start; + finished = true; + fn(err); + } + + // for .resetTimeout() + this.callback = done; + + // async + if (this.async) { + try { + this.fn.call(ctx, function(err){ + if (err instanceof Error) return done(err); + if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); + done(); + }); + } catch (err) { + done(err); + } + return; + } + + // sync + try { + if (!this.pending) this.fn.call(ctx); + this.duration = new Date - start; + fn(); + } catch (err) { + fn(err); + } +}; + +}); // module: runnable.js + +require.register("runner.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runner') + , Test = require('./test') + , utils = require('./utils') + , filter = utils.filter + , keys = utils.keys + , noop = function(){}; + +/** + * Expose `Runner`. + */ + +module.exports = Runner; + +/** + * Initialize a `Runner` for the given `suite`. + * + * Events: + * + * - `start` execution started + * - `end` execution complete + * - `suite` (suite) test suite execution started + * - `suite end` (suite) all tests (and sub-suites) have finished + * - `test` (test) test execution started + * - `test end` (test) test completed + * - `hook` (hook) hook execution started + * - `hook end` (hook) hook complete + * - `pass` (test) test passed + * - `fail` (test, err) test failed + * + * @api public + */ + +function Runner(suite) { + var self = this; + this._globals = []; + this.suite = suite; + this.total = suite.total(); + this.failures = 0; + this.on('test end', function(test){ self.checkGlobals(test); }); + this.on('hook end', function(hook){ self.checkGlobals(hook); }); + this.grep(/.*/); + this.globals(utils.keys(global).concat(['errno'])); +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Runner.prototype = new EventEmitter; +Runner.prototype.constructor = Runner; + + +/** + * Run tests with full titles matching `re`. Updates runner.total + * with number of tests matched. + * + * @param {RegExp} re + * @param {Boolean} invert + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.grep = function(re, invert){ + debug('grep %s', re); + this._grep = re; + this._invert = invert; + this.total = this.grepTotal(this.suite); + return this; +}; + +/** + * Returns the number of tests matching the grep search for the + * given suite. + * + * @param {Suite} suite + * @return {Number} + * @api public + */ + +Runner.prototype.grepTotal = function(suite) { + var self = this; + var total = 0; + + suite.eachTest(function(test){ + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (match) total++; + }); + + return total; +}; + +/** + * Allow the given `arr` of globals. + * + * @param {Array} arr + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.globals = function(arr){ + if (0 == arguments.length) return this._globals; + debug('globals %j', arr); + utils.forEach(arr, function(arr){ + this._globals.push(arr); + }, this); + return this; +}; + +/** + * Check for global variable leaks. + * + * @api private + */ + +Runner.prototype.checkGlobals = function(test){ + if (this.ignoreLeaks) return; + var leaks = filterLeaks(this._globals); + + this._globals = this._globals.concat(leaks); + + if (leaks.length > 1) { + this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); + } else if (leaks.length) { + this.fail(test, new Error('global leak detected: ' + leaks[0])); + } +}; + +/** + * Fail the given `test`. + * + * @param {Test} test + * @param {Error} err + * @api private + */ + +Runner.prototype.fail = function(test, err){ + ++this.failures; + test.state = 'failed'; + if ('string' == typeof err) { + err = new Error('the string "' + err + '" was thrown, throw an Error :)'); + } + this.emit('fail', test, err); +}; + +/** + * Fail the given `hook` with `err`. + * + * Hook failures (currently) hard-end due + * to that fact that a failing hook will + * surely cause subsequent tests to fail, + * causing jumbled reporting. + * + * @param {Hook} hook + * @param {Error} err + * @api private + */ + +Runner.prototype.failHook = function(hook, err){ + this.fail(hook, err); + this.emit('end'); +}; + +/** + * Run hook `name` callbacks and then invoke `fn()`. + * + * @param {String} name + * @param {Function} function + * @api private + */ + +Runner.prototype.hook = function(name, fn){ + var suite = this.suite + , hooks = suite['_' + name] + , ms = suite._timeout + , self = this + , timer; + + function next(i) { + var hook = hooks[i]; + if (!hook) return fn(); + self.currentRunnable = hook; + + self.emit('hook', hook); + + hook.on('error', function(err){ + self.failHook(hook, err); + }); + + hook.run(function(err){ + hook.removeAllListeners('error'); + var testError = hook.error(); + if (testError) self.fail(self.test, testError); + if (err) return self.failHook(hook, err); + self.emit('hook end', hook); + next(++i); + }); + } + + process.nextTick(function(){ + next(0); + }); +}; + +/** + * Run hook `name` for the given array of `suites` + * in order, and callback `fn(err)`. + * + * @param {String} name + * @param {Array} suites + * @param {Function} fn + * @api private + */ + +Runner.prototype.hooks = function(name, suites, fn){ + var self = this + , orig = this.suite; + + function next(suite) { + self.suite = suite; + + if (!suite) { + self.suite = orig; + return fn(); + } + + self.hook(name, function(err){ + if (err) { + self.suite = orig; + return fn(err); + } + + next(suites.pop()); + }); + } + + next(suites.pop()); +}; + +/** + * Run hooks from the top level down. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookUp = function(name, fn){ + var suites = [this.suite].concat(this.parents()).reverse(); + this.hooks(name, suites, fn); +}; + +/** + * Run hooks from the bottom up. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookDown = function(name, fn){ + var suites = [this.suite].concat(this.parents()); + this.hooks(name, suites, fn); +}; + +/** + * Return an array of parent Suites from + * closest to furthest. + * + * @return {Array} + * @api private + */ + +Runner.prototype.parents = function(){ + var suite = this.suite + , suites = []; + while (suite = suite.parent) suites.push(suite); + return suites; +}; + +/** + * Run the current test and callback `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTest = function(fn){ + var test = this.test + , self = this; + + try { + test.on('error', function(err){ + self.fail(test, err); + }); + test.run(fn); + } catch (err) { + fn(err); + } +}; + +/** + * Run tests in the given `suite` and invoke + * the callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTests = function(suite, fn){ + var self = this + , tests = suite.tests + , test; + + function next(err) { + // if we bail after first err + if (self.failures && suite._bail) return fn(); + + // next test + test = tests.shift(); + + // all done + if (!test) return fn(); + + // grep + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (!match) return next(); + + // pending + if (test.pending) { + self.emit('pending', test); + self.emit('test end', test); + return next(); + } + + // execute test and hook(s) + self.emit('test', self.test = test); + self.hookDown('beforeEach', function(){ + self.currentRunnable = self.test; + self.runTest(function(err){ + test = self.test; + + if (err) { + self.fail(test, err); + self.emit('test end', test); + return self.hookUp('afterEach', next); + } + + test.state = 'passed'; + self.emit('pass', test); + self.emit('test end', test); + self.hookUp('afterEach', next); + }); + }); + } + + this.next = next; + next(); +}; + +/** + * Run the given `suite` and invoke the + * callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runSuite = function(suite, fn){ + var total = this.grepTotal(suite) + , self = this + , i = 0; + + debug('run suite %s', suite.fullTitle()); + + if (!total) return fn(); + + this.emit('suite', this.suite = suite); + + function next() { + var curr = suite.suites[i++]; + if (!curr) return done(); + self.runSuite(curr, next); + } + + function done() { + self.suite = suite; + self.hook('afterAll', function(){ + self.emit('suite end', suite); + fn(); + }); + } + + this.hook('beforeAll', function(){ + self.runTests(suite, next); + }); +}; + +/** + * Handle uncaught exceptions. + * + * @param {Error} err + * @api private + */ + +Runner.prototype.uncaught = function(err){ + debug('uncaught exception %s', err.message); + var runnable = this.currentRunnable; + if (!runnable || 'failed' == runnable.state) return; + runnable.clearTimeout(); + err.uncaught = true; + this.fail(runnable, err); + + // recover from test + if ('test' == runnable.type) { + this.emit('test end', runnable); + this.hookUp('afterEach', this.next); + return; + } + + // bail on hooks + this.emit('end'); +}; + +/** + * Run the root suite and invoke `fn(failures)` + * on completion. + * + * @param {Function} fn + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.run = function(fn){ + var self = this + , fn = fn || function(){}; + + debug('start'); + + // uncaught callback + function uncaught(err) { + self.uncaught(err); + } + + // callback + this.on('end', function(){ + debug('end'); + process.removeListener('uncaughtException', uncaught); + fn(self.failures); + }); + + // run suites + this.emit('start'); + this.runSuite(this.suite, function(){ + debug('finished running'); + self.emit('end'); + }); + + // uncaught exception + process.on('uncaughtException', uncaught); + + return this; +}; + +/** + * Filter leaks with the given globals flagged as `ok`. + * + * @param {Array} ok + * @return {Array} + * @api private + */ + +function filterLeaks(ok) { + return filter(keys(global), function(key){ + var matched = filter(ok, function(ok){ + if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); + return key == ok; + }); + return matched.length == 0 && (!global.navigator || 'onerror' !== key); + }); +} +}); // module: runner.js + +require.register("suite.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:suite') + , utils = require('./utils') + , Hook = require('./hook'); + +/** + * Expose `Suite`. + */ + +exports = module.exports = Suite; + +/** + * Create a new `Suite` with the given `title` + * and parent `Suite`. When a suite with the + * same title is already present, that suite + * is returned to provide nicer reporter + * and more flexible meta-testing. + * + * @param {Suite} parent + * @param {String} title + * @return {Suite} + * @api public + */ + +exports.create = function(parent, title){ + var suite = new Suite(title, parent.ctx); + suite.parent = parent; + if (parent.pending) suite.pending = true; + title = suite.fullTitle(); + parent.addSuite(suite); + return suite; +}; + +/** + * Initialize a new `Suite` with the given + * `title` and `ctx`. + * + * @param {String} title + * @param {Context} ctx + * @api private + */ + +function Suite(title, ctx) { + this.title = title; + this.ctx = ctx; + this.suites = []; + this.tests = []; + this.pending = false; + this._beforeEach = []; + this._beforeAll = []; + this._afterEach = []; + this._afterAll = []; + this.root = !title; + this._timeout = 2000; + this._bail = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Suite.prototype = new EventEmitter; +Suite.prototype.constructor = Suite; + + +/** + * Return a clone of this `Suite`. + * + * @return {Suite} + * @api private + */ + +Suite.prototype.clone = function(){ + var suite = new Suite(this.title); + debug('clone'); + suite.ctx = this.ctx; + suite.timeout(this.timeout()); + suite.bail(this.bail()); + return suite; +}; + +/** + * Set timeout `ms` or short-hand such as "2s". + * + * @param {Number|String} ms + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000; + debug('timeout %d', ms); + this._timeout = parseInt(ms, 10); + return this; +}; + +/** + * Sets whether to bail after first error. + * + * @parma {Boolean} bail + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.bail = function(bail){ + if (0 == arguments.length) return this._bail; + debug('bail %s', bail); + this._bail = bail; + return this; +}; + +/** + * Run `fn(test[, done])` before running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.beforeAll = function(fn){ + if (this.pending) return this; + var hook = new Hook('"before all" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._beforeAll.push(hook); + this.emit('beforeAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.afterAll = function(fn){ + if (this.pending) return this; + var hook = new Hook('"after all" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._afterAll.push(hook); + this.emit('afterAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` before each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.beforeEach = function(fn){ + if (this.pending) return this; + var hook = new Hook('"before each" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._beforeEach.push(hook); + this.emit('beforeEach', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.afterEach = function(fn){ + if (this.pending) return this; + var hook = new Hook('"after each" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._afterEach.push(hook); + this.emit('afterEach', hook); + return this; +}; + +/** + * Add a test `suite`. + * + * @param {Suite} suite + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addSuite = function(suite){ + suite.parent = this; + suite.timeout(this.timeout()); + suite.bail(this.bail()); + this.suites.push(suite); + this.emit('suite', suite); + return this; +}; + +/** + * Add a `test` to this suite. + * + * @param {Test} test + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addTest = function(test){ + test.parent = this; + test.timeout(this.timeout()); + test.ctx = this.ctx; + this.tests.push(test); + this.emit('test', test); + return this; +}; + +/** + * Return the full title generated by recursively + * concatenating the parent's full title. + * + * @return {String} + * @api public + */ + +Suite.prototype.fullTitle = function(){ + if (this.parent) { + var full = this.parent.fullTitle(); + if (full) return full + ' ' + this.title; + } + return this.title; +}; + +/** + * Return the total number of tests. + * + * @return {Number} + * @api public + */ + +Suite.prototype.total = function(){ + return utils.reduce(this.suites, function(sum, suite){ + return sum + suite.total(); + }, 0) + this.tests.length; +}; + +/** + * Iterates through each suite recursively to find + * all tests. Applies a function in the format + * `fn(test)`. + * + * @param {Function} fn + * @return {Suite} + * @api private + */ + +Suite.prototype.eachTest = function(fn){ + utils.forEach(this.tests, fn); + utils.forEach(this.suites, function(suite){ + suite.eachTest(fn); + }); + return this; +}; + +}); // module: suite.js + +require.register("test.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Test`. + */ + +module.exports = Test; + +/** + * Initialize a new `Test` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Test(title, fn) { + Runnable.call(this, title, fn); + this.pending = !fn; + this.type = 'test'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +Test.prototype = new Runnable; +Test.prototype.constructor = Test; + + +}); // module: test.js + +require.register("utils.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var fs = require('browser/fs') + , path = require('browser/path') + , join = path.join + , debug = require('browser/debug')('mocha:watch'); + +/** + * Ignored directories. + */ + +var ignore = ['node_modules', '.git']; + +/** + * Escape special characters in the given string of html. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html) { + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +}; + +/** + * Array#forEach (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} scope + * @api private + */ + +exports.forEach = function(arr, fn, scope) { + for (var i = 0, l = arr.length; i < l; i++) + fn.call(scope, arr[i], i); +}; + +/** + * Array#indexOf (<=IE8) + * + * @parma {Array} arr + * @param {Object} obj to find index of + * @param {Number} start + * @api private + */ + +exports.indexOf = function (arr, obj, start) { + for (var i = start || 0, l = arr.length; i < l; i++) { + if (arr[i] === obj) + return i; + } + return -1; +}; + +/** + * Array#reduce (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} initial value + * @param {Object} scope + * @api private + */ + +exports.reduce = function(arr, fn, val, scope) { + var rval = val; + + for (var i = 0, l = arr.length; i < l; i++) { + rval = fn.call(scope, rval, arr[i], i, arr); + } + + return rval; +}; + +/** + * Array#filter (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} scope + * @api private + */ + +exports.filter = function(arr, fn, scope) { + var ret = []; + + for (var i = 0, l = arr.length; i < l; i++) { + var val = arr[i]; + if (fn.call(scope, val, i, arr)) + ret.push(val); + } + + return ret; +}; + +/** + * Object.keys (<=IE8) + * + * @param {Object} obj + * @return {Array} keys + * @api private + */ + +exports.keys = Object.keys || function(obj) { + var keys = [] + , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 + + for (var key in obj) { + if (has.call(obj, key)) { + keys.push(key); + } + } + + return keys; +}; + +/** + * Watch the given `files` for changes + * and invoke `fn(file)` on modification. + * + * @param {Array} files + * @param {Function} fn + * @api private + */ + +exports.watch = function(files, fn){ + var options = { interval: 100 }; + files.forEach(function(file){ + debug('file %s', file); + fs.watchFile(file, options, function(curr, prev){ + if (prev.mtime < curr.mtime) fn(file); + }); + }); +}; + +/** + * Ignored files. + */ + +function ignored(path){ + return !~ignore.indexOf(path); +} + +/** + * Lookup files in the given `dir`. + * + * @return {Array} + * @api private + */ + +exports.files = function(dir, ret){ + ret = ret || []; + + fs.readdirSync(dir) + .filter(ignored) + .forEach(function(path){ + path = join(dir, path); + if (fs.statSync(path).isDirectory()) { + exports.files(path, ret); + } else if (path.match(/\.(js|coffee)$/)) { + ret.push(path); + } + }); + + return ret; +}; + +/** + * Compute a slug from the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.slug = function(str){ + return str + .toLowerCase() + .replace(/ +/g, '-') + .replace(/[^-\w]/g, ''); +}; + +/** + * Strip the function definition from `str`, + * and re-indent for pre whitespace. + */ + +exports.clean = function(str) { + str = str + .replace(/^function *\(.*\) *{/, '') + .replace(/\s+\}$/, ''); + + var spaces = str.match(/^\n?( *)/)[1].length + , re = new RegExp('^ {' + spaces + '}', 'gm'); + + str = str.replace(re, ''); + + return exports.trim(str); +}; + +/** + * Escape regular expression characters in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.escapeRegexp = function(str){ + return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); +}; + +/** + * Trim the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.trim = function(str){ + return str.replace(/^\s+|\s+$/g, ''); +}; + +/** + * Parse the given `qs`. + * + * @param {String} qs + * @return {Object} + * @api private + */ + +exports.parseQuery = function(qs){ + return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ + var i = pair.indexOf('=') + , key = pair.slice(0, i) + , val = pair.slice(++i); + + obj[key] = decodeURIComponent(val); + return obj; + }, {}); +}; + +/** + * Highlight the given string of `js`. + * + * @param {String} js + * @return {String} + * @api private + */ + +function highlight(js) { + return js + .replace(//g, '>') + .replace(/\/\/(.*)/gm, '//$1') + .replace(/('.*?')/gm, '$1') + .replace(/(\d+\.\d+)/gm, '$1') + .replace(/(\d+)/gm, '$1') + .replace(/\bnew *(\w+)/gm, 'new $1') + .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') +} + +/** + * Highlight the contents of tag `name`. + * + * @param {String} name + * @api private + */ + +exports.highlightTags = function(name) { + var code = document.getElementsByTagName(name); + for (var i = 0, len = code.length; i < len; ++i) { + code[i].innerHTML = highlight(code[i].innerHTML); + } +}; +}); // module: utils.js +/** + * Node shims. + * + * These are meant only to allow + * mocha.js to run untouched, not + * to allow running node code in + * the browser. + */ + +process = {}; +process.exit = function(status){}; +process.stdout = {}; +global = window; + +/** + * next tick implementation. + */ + +process.nextTick = (function(){ + // postMessage behaves badly on IE8 + if (window.ActiveXObject || !window.postMessage) { + return function(fn){ fn() }; + } + + // based on setZeroTimeout by David Baron + // - http://dbaron.org/log/20100309-faster-timeouts + var timeouts = [] + , name = 'mocha-zero-timeout' + + window.addEventListener('message', function(e){ + if (e.source == window && e.data == name) { + if (e.stopPropagation) e.stopPropagation(); + if (timeouts.length) timeouts.shift()(); + } + }, true); + + return function(fn){ + timeouts.push(fn); + window.postMessage(name, '*'); + } +})(); + +/** + * Remove uncaughtException listener. + */ + +process.removeListener = function(e){ + if ('uncaughtException' == e) { + window.onerror = null; + } +}; + +/** + * Implements uncaughtException listener. + */ + +process.on = function(e, fn){ + if ('uncaughtException' == e) { + window.onerror = fn; + } +}; + +// boot +;(function(){ + + /** + * Expose mocha. + */ + + var Mocha = window.Mocha = require('mocha'), + mocha = window.mocha = new Mocha({ reporter: 'html' }); + + /** + * Override ui to ensure that the ui functions are initialized. + * Normally this would happen in Mocha.prototype.loadFiles. + */ + + mocha.ui = function(ui){ + Mocha.prototype.ui.call(this, ui); + this.suite.emit('pre-require', window, null, this); + return this; + }; + + /** + * Setup mocha with the given setting options. + */ + + mocha.setup = function(opts){ + if ('string' == typeof opts) opts = { ui: opts }; + for (var opt in opts) this[opt](opts[opt]); + return this; + }; + + /** + * Run mocha, returning the Runner. + */ + + mocha.run = function(fn){ + var options = mocha.options; + mocha.globals('location'); + + var query = Mocha.utils.parseQuery(window.location.search || ''); + if (query.grep) mocha.grep(query.grep); + + return Mocha.prototype.run.call(mocha, function(){ + Mocha.utils.highlightTags('code'); + if (fn) fn(); + }); + }; +})(); +})(); \ No newline at end of file diff --git a/node_modules/component-matches-selector/test/tests.js b/node_modules/component-matches-selector/test/tests.js new file mode 100644 index 00000000..f385309e --- /dev/null +++ b/node_modules/component-matches-selector/test/tests.js @@ -0,0 +1,35 @@ + +var matches = require('matches-selector') + , domify = require('domify'); + +function assert(expr) { + if (!expr) throw new Error('assertion failed'); +} + +var ul = domify('
    • foo
    '); +var li = ul.children[0]; +var em = li.children[0]; + +describe('matchesSelector(el, selector)', function(){ + it('should work', function(){ + assert(true === matches(em, 'ul li em')); + assert(true === matches(em, 'ul em')); + assert(true === matches(em, 'ul > li > em')); + assert(false === matches(em, 'ul ul em')); + + assert(true === matches(li, 'ul li')); + assert(true === matches(li, 'ul > li')); + assert(true === matches(li, 'li')); + assert(false === matches(li, 'div > li')); + + assert(true == matches(ul, 'ul')); + assert(false == matches(ul, 'div ul')); + assert(false == matches(ul, 'body > ul')); + }) + it('should not throw an Error when given `null`', function(){ + assert(false == matches(null, 'ul')); + }) + it('should not throw an Error when given a TextNode', function(){ + assert(false == matches(em.firstChild, 'ul')); + }) +}) diff --git a/node_modules/component-query/.npmignore b/node_modules/component-query/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/component-query/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/component-query/History.md b/node_modules/component-query/History.md new file mode 100644 index 00000000..742926b4 --- /dev/null +++ b/node_modules/component-query/History.md @@ -0,0 +1,18 @@ + +0.0.3 / 2014-02-10 +================== + + * package: rename to "component-query" + * package: add "component" section + * component: beautify "keywords" + +0.0.2 / 2013-11-01 +================== + + * return exports on `exports.engine()` + * add `package.json` file + +0.0.1 / 2013-03-14 +================== + + * initial commit diff --git a/node_modules/component-query/Makefile b/node_modules/component-query/Makefile new file mode 100644 index 00000000..0f14dac3 --- /dev/null +++ b/node_modules/component-query/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components template.js + +.PHONY: clean diff --git a/node_modules/component-query/Readme.md b/node_modules/component-query/Readme.md new file mode 100644 index 00000000..d1449a12 --- /dev/null +++ b/node_modules/component-query/Readme.md @@ -0,0 +1,42 @@ +# query + + Query the DOM with selector engine fallback support. This abstraction + allows all other components that require dom querying to indirectly support + old browsers, without explicitly adding support for them. + +## Installation + + $ component install component/query + +## API + +### query(selector, [el]) + + Query `selector` against the document or `el` + and return a single match. + +```js +query('ul > li'); +query('ul > li', articles); +``` + +### query.all(selector, [el]) + + Query `selector` against the document or `el` + and return all matches. + +```js +query.all('ul > li'); +query.all('ul > li', articles); +``` + +## Fallback engines + + Currently supported: + + - [query-zest](https://github.com/component/query-zest) + - [query-qwery](https://github.com/jamischarles/query-qwery) + +## License + + MIT diff --git a/node_modules/component-query/component.json b/node_modules/component-query/component.json new file mode 100644 index 00000000..13e225df --- /dev/null +++ b/node_modules/component-query/component.json @@ -0,0 +1,21 @@ +{ + "name": "query", + "repo": "component/query", + "description": "Query the DOM with selector engine fallback support", + "version": "0.0.3", + "keywords": [ + "query", + "selector", + "engine", + "dom", + "elements" + ], + "dependencies": {}, + "development": { + "component/assert": "*" + }, + "license": "MIT", + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-query/example.html b/node_modules/component-query/example.html new file mode 100644 index 00000000..e04a8fab --- /dev/null +++ b/node_modules/component-query/example.html @@ -0,0 +1,19 @@ + + + Query + + +
      +
    • one
    • +
    • two
    • +
    • three
    • +
    + + + + + diff --git a/node_modules/component-query/index.js b/node_modules/component-query/index.js new file mode 100644 index 00000000..cd2cf3a0 --- /dev/null +++ b/node_modules/component-query/index.js @@ -0,0 +1,21 @@ +function one(selector, el) { + return el.querySelector(selector); +} + +exports = module.exports = function(selector, el){ + el = el || document; + return one(selector, el); +}; + +exports.all = function(selector, el){ + el = el || document; + return el.querySelectorAll(selector); +}; + +exports.engine = function(obj){ + if (!obj.one) throw new Error('.one callback required'); + if (!obj.all) throw new Error('.all callback required'); + one = obj.one; + exports.all = obj.all; + return exports; +}; diff --git a/node_modules/component-query/package.json b/node_modules/component-query/package.json new file mode 100644 index 00000000..b9c0a480 --- /dev/null +++ b/node_modules/component-query/package.json @@ -0,0 +1,24 @@ +{ + "name": "component-query", + "description": "Query the DOM with selector engine fallback support", + "version": "0.0.3", + "keywords": [ + "query", + "selector", + "engine", + "dom", + "elements" + ], + "dependencies": {}, + "license": "MIT", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/component/query.git" + }, + "component": { + "scripts": { + "query/index.js": "index.js" + } + } +} diff --git a/node_modules/component-raf/.npmignore b/node_modules/component-raf/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/component-raf/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/component-raf/History.md b/node_modules/component-raf/History.md new file mode 100644 index 00000000..64619234 --- /dev/null +++ b/node_modules/component-raf/History.md @@ -0,0 +1,26 @@ + +1.2.0 / 2014-09-14 +================== + + * remove never implemented -o and -ms prefixes (@darsain) + +1.1.3 / 2014-02-11 +================== + + * package: rename to "component-raf" + * package: add "main" field + +1.1.2 / 2013-07-12 +================== + + * fix .cancel() with fallback #4 @ilsken + +1.1.1 / 2013-07-12 +================== + + * fix .cancel(), bitches when window is not the receiver... + +1.1.0 / 2013-07-12 +================== + + * add .cancel(id) diff --git a/node_modules/component-raf/Makefile b/node_modules/component-raf/Makefile new file mode 100644 index 00000000..84395cdd --- /dev/null +++ b/node_modules/component-raf/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build --dev + +components: + @component install --dev + +clean: + rm -fr build components template.js + +.PHONY: clean diff --git a/node_modules/component-raf/Readme.md b/node_modules/component-raf/Readme.md new file mode 100644 index 00000000..18733a56 --- /dev/null +++ b/node_modules/component-raf/Readme.md @@ -0,0 +1,46 @@ + +# raf + + request animation frame + +## Installation + + $ component install component/raf + +## Example + + Request the animation frame with `raf(fn)`, cancel with `raf.cancel(id)`. + +```js +var x = 0; +var y = 50; +var canvas = document.querySelector('canvas'); +var ctx = canvas.getContext('2d'); +var raf = require('raf'); + +function animate() { + raf(animate); + draw(); +} + +var prev = Date.now(); +function draw() { + var curr = Date.now(); + var diff = curr - prev; + var p = diff / 16; + ctx.clearRect(0, 0, 900, 300); + ctx.beginPath(); + ctx.globalAlpha = .5; + ctx.arc(x, y, 10, 0, Math.PI * 2, false); + ctx.fill(); + x += 2; + y += Math.sin(x/20) * 5; + prev = curr; +} + +animate(); +``` + +## License + + MIT diff --git a/node_modules/component-raf/component.json b/node_modules/component-raf/component.json new file mode 100644 index 00000000..af85119b --- /dev/null +++ b/node_modules/component-raf/component.json @@ -0,0 +1,16 @@ +{ + "name": "raf", + "repo": "component/raf", + "description": "request animation frame", + "version": "1.2.0", + "keywords": [ + "animate", + "requestAnimationFrame", + "performance" + ], + "dependencies": {}, + "development": {}, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-raf/example.html b/node_modules/component-raf/example.html new file mode 100644 index 00000000..d26e87aa --- /dev/null +++ b/node_modules/component-raf/example.html @@ -0,0 +1,43 @@ + + + + + + + + \ No newline at end of file diff --git a/node_modules/component-raf/index.js b/node_modules/component-raf/index.js new file mode 100644 index 00000000..4c72fe2b --- /dev/null +++ b/node_modules/component-raf/index.js @@ -0,0 +1,34 @@ +/** + * Expose `requestAnimationFrame()`. + */ + +exports = module.exports = window.requestAnimationFrame + || window.webkitRequestAnimationFrame + || window.mozRequestAnimationFrame + || fallback; + +/** + * Fallback implementation. + */ + +var prev = new Date().getTime(); +function fallback(fn) { + var curr = new Date().getTime(); + var ms = Math.max(0, 16 - (curr - prev)); + var req = setTimeout(fn, ms); + prev = curr; + return req; +} + +/** + * Cancel. + */ + +var cancel = window.cancelAnimationFrame + || window.webkitCancelAnimationFrame + || window.mozCancelAnimationFrame + || window.clearTimeout; + +exports.cancel = function(id){ + cancel.call(window, id); +}; diff --git a/node_modules/component-raf/package.json b/node_modules/component-raf/package.json new file mode 100644 index 00000000..c96d6e11 --- /dev/null +++ b/node_modules/component-raf/package.json @@ -0,0 +1,21 @@ +{ + "name": "component-raf", + "description": "request animation frame", + "version": "1.2.0", + "keywords": [ + "animate", + "requestAnimationFrame", + "performance" + ], + "dependencies": {}, + "component": { + "scripts": { + "raf/index.js": "index.js" + } + }, + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/component/raf.git" + } +} diff --git a/node_modules/component-tap-event/LICENSE b/node_modules/component-tap-event/LICENSE new file mode 100644 index 00000000..d26fb77d --- /dev/null +++ b/node_modules/component-tap-event/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2015 Jonathan Ong me@jongleberry.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/component-tap-event/README.md b/node_modules/component-tap-event/README.md new file mode 100644 index 00000000..a6b2a69a --- /dev/null +++ b/node_modules/component-tap-event/README.md @@ -0,0 +1,63 @@ +# Tap Event + +[![Build Status](https://secure.travis-ci.org/chemzqm/tap-event.svg)](http://travis-ci.org/chemzqm/tap-event) + +Make your `touchstart` event listeners into a `tap` event listener! + +What is "correct" behavior? The `tap` event: + +- shouldn't be triggered until the user removes his/her finger from the surface of the screen. +- shouldn't be triggered when the user moves his/her finger at all (ie it should not interfere with drag events). +- shouldn't be triggered if there's ever more than a single finger on the surface at all. +- should never trigger the `click` event. + +Preserve context and arguments in 1.1.0, works with delegate easily + +## Install + + npm install component-tap-event -S + +## API + +```js +var tap = require('tap-event') + +var el = document.querySelector('#container') + +// the event you want to handle +function changeLocation(e) { + // e.preventDefault() is already called! + location.href = this.href +} + +// wrap the listener +var listener = tap(changeLocation) + +// listen to `touchstart` +el.addEventListener('touchstart', listener) + +// remove the listener +el.removeEventListener('touchstart', listener) +``` + +or, more succinctly: + +```js +document.querySelector('#container').addEventListener('touchstart', tap(function (e) { + location.href = this.href +})) +``` + +To set a custom timeout (default is `200ms`), you have two options: + +```js +// set globally +tap.timeout = 300 + +// set per instance +tap(function (e) { + +}, { + timeout: 300 +}) +``` diff --git a/node_modules/component-tap-event/index.js b/node_modules/component-tap-event/index.js new file mode 100644 index 00000000..ada15cf4 --- /dev/null +++ b/node_modules/component-tap-event/index.js @@ -0,0 +1,87 @@ +var endEvents = [ + 'touchend' +] + +module.exports = Tap + +// default tap timeout in ms +Tap.timeout = 200 + +function Tap(callback, options) { + options = options || {} + // if the user holds his/her finger down for more than 200ms, + // then it's not really considered a tap. + // however, you can make this configurable. + var timeout = options.timeout || Tap.timeout + + // to keep track of the original listener + listener.handler = callback + + return listener + + // el.addEventListener('touchstart', listener) + function listener(e1) { + // tap should only happen with a single finger + if (!e1.touches || e1.touches.length > 1) return + + var el = e1.target + var context = this + var args = arguments; + + var timeout_id = setTimeout(cleanup, timeout) + + el.addEventListener('touchmove', cleanup) + + endEvents.forEach(function (event) { + el.addEventListener(event, done) + }) + + function done(e2) { + // since touchstart is added on the same tick + // and because of bubbling, + // it'll execute this on the same touchstart. + // this filters out the same touchstart event. + if (e1 === e2) return + + cleanup() + + // already handled + if (e2.defaultPrevented) return + + // overwrite these functions so that they all to both start and events. + var preventDefault = e1.preventDefault + var stopPropagation = e1.stopPropagation + + e1.stopPropagation = function () { + stopPropagation.call(e1) + stopPropagation.call(e2) + } + + e1.preventDefault = function () { + //preventDefault.call(e1) + preventDefault.call(e2) + } + + // calls the handler with the `end` event, + // but i don't think it matters. + callback.apply(context, args) + } + + // cleanup end events + // to cancel the tap, just run this early + function cleanup(e2) { + // if it's the same event as the origin, + // then don't actually cleanup. + // hit issues with this - don't remember + if (e1 === e2) return + + clearTimeout(timeout_id) + + el.removeEventListener('touchmove', cleanup) + + endEvents.forEach(function (event) { + el.removeEventListener(event, done) + }) + } + } +} diff --git a/node_modules/component-tap-event/package.json b/node_modules/component-tap-event/package.json new file mode 100644 index 00000000..73c8adae --- /dev/null +++ b/node_modules/component-tap-event/package.json @@ -0,0 +1,38 @@ +{ + "name": "component-tap-event", + "description": "Create tap event listeners", + "version": "1.1.4", + "license": "MIT", + "repository": "https://github.com/chemzqm/tap-event", + "keywords": [ + "tap", + "event", + "listener" + ], + "main": "index.js", + "files": [ + "index.js" + ], + "devDependencies": { + "coveralls": "^2.11.4", + "istanbul": "^0.4.0", + "istanbul-instrumenter-loader": "^0.2.0", + "karma": "^0.13.15", + "karma-cli": "^0.1.1", + "karma-coverage": "^0.5.3", + "karma-firefox-launcher": "^0.1.7", + "karma-mocha": "^0.2.0", + "karma-webpack": "^1.7.0", + "karma-wrap-preprocessor": "^0.1.0", + "mocha": "^2.3.3", + "mocha-loader": "^0.7.1", + "standardberry": "^3.5.1", + "touch-simulate": "^0.1.1", + "webpack": "^1.12.4", + "webpack-dev-server": "^1.12.1" + }, + "scripts": { + "test": "make test-karma" + }, + "browser": {} +} diff --git a/node_modules/component-tween/.npmignore b/node_modules/component-tween/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/component-tween/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/component-tween/History.md b/node_modules/component-tween/History.md new file mode 100644 index 00000000..0bacf40d --- /dev/null +++ b/node_modules/component-tween/History.md @@ -0,0 +1,27 @@ + +1.2.0 / 2015-03-16 +================== + + * update "emitter" to v1.2.0 + * use "component-clone" and "component-type" for browsers support (#5, @cristiandouce) + * update component.json (#4, @pgherveou) + * package: add browserify mappings (#7, @dfcreative) + * package: add "repository" field (#3) + +1.1.0 / 2013-05-29 +================== + + * add Tween#stop(). Closes #2 + * fix final update to complete the tween. Closes #1 + +1.0.0 / 2013-05-27 +================== + + * pin deps + * add package.json + * add interactive example + +0.1.0 / 2012-11-10 +================== + + * add array tweening support diff --git a/node_modules/component-tween/Makefile b/node_modules/component-tween/Makefile new file mode 100644 index 00000000..9388265f --- /dev/null +++ b/node_modules/component-tween/Makefile @@ -0,0 +1,16 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components template.js + +tween.js: + @component build --standalone tween \ + && mv build/build.js $@ \ + && rm -fr build + +.PHONY: clean tween.js diff --git a/node_modules/component-tween/Readme.md b/node_modules/component-tween/Readme.md new file mode 100644 index 00000000..13ce8dde --- /dev/null +++ b/node_modules/component-tween/Readme.md @@ -0,0 +1,78 @@ + +# tween + + Motion tween component using [ease](https://github.com/component/ease). + +## Installation + + $ component install component/tween + +## Example + +```js +var Tween = require('tween'); +var raf = require('raf'); +var button = document.querySelector('button'); + +var tween = Tween({ rotate: 0, opacity: 0 }) + .ease('out-bounce') + .to({ rotate: 360, opacity: 1 }) + .duration(800); + +tween.update(function(o){ + button.style.opacity = o.opacity; + button.style.webkitTransform = 'rotate(' + (o.rotate | 0) + 'deg)'; +}); + +tween.on('end', function(){ + animate = function(){}; +}); + +function animate() { + raf(animate); + tween.update(); +} + +animate(); +``` + +## API + +### Tween(obj:Object|Array) + + Initialize a new `Tween` with `obj`. + +### Tween#reset() + + Reset the tween. + +### Tween#to(obj:Object|Array) + + Tween to `obj` and reset internal state. + + tween.to({ x: 50, y: 100 }) + +### Tween#duration(ms:Number) + + Set duration to `ms` [500]. + +### Tween#ease(fn:String|Function) + + Set easing function to `fn`. + + tween.ease('in-out-sine') + +### Tween#update(fn:Function) + + Set update function to `fn` or + when no argument is given this performs + a "step". + +### Tween#stop() + + Immediately stop the tween and emit "stop" and end" events. `tween.stopped` + is then marked as `true`. + +## License + + MIT diff --git a/node_modules/component-tween/component.json b/node_modules/component-tween/component.json new file mode 100644 index 00000000..87e94682 --- /dev/null +++ b/node_modules/component-tween/component.json @@ -0,0 +1,25 @@ +{ + "name": "tween", + "repo": "component/tween", + "description": "Motion tween engine using 'ease'", + "version": "1.2.0", + "keywords": [ + "tween", + "tweening", + "animation" + ], + "dependencies": { + "component/clone": "0.2.2", + "component/ease": "1.0.0", + "component/emitter": "1.2.0", + "component/type": "1.1.0" + }, + "development": { + "component/raf": "*", + "component/autoscale-canvas": "*" + }, + "license": "MIT", + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-tween/examples/array.html b/node_modules/component-tween/examples/array.html new file mode 100644 index 00000000..e304f6e5 --- /dev/null +++ b/node_modules/component-tween/examples/array.html @@ -0,0 +1,48 @@ + + + + + + + + \ No newline at end of file diff --git a/node_modules/component-tween/examples/ball.html b/node_modules/component-tween/examples/ball.html new file mode 100644 index 00000000..280af75b --- /dev/null +++ b/node_modules/component-tween/examples/ball.html @@ -0,0 +1,64 @@ + + + + + + + + diff --git a/node_modules/component-tween/examples/circle.html b/node_modules/component-tween/examples/circle.html new file mode 100644 index 00000000..64e50e56 --- /dev/null +++ b/node_modules/component-tween/examples/circle.html @@ -0,0 +1,45 @@ + + + + + + + + + + diff --git a/node_modules/component-tween/examples/dom.html b/node_modules/component-tween/examples/dom.html new file mode 100644 index 00000000..e9db878b --- /dev/null +++ b/node_modules/component-tween/examples/dom.html @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/node_modules/component-tween/examples/interactive.html b/node_modules/component-tween/examples/interactive.html new file mode 100644 index 00000000..86bb0e2b --- /dev/null +++ b/node_modules/component-tween/examples/interactive.html @@ -0,0 +1,62 @@ + + + + + + + + \ No newline at end of file diff --git a/node_modules/component-tween/examples/rect.html b/node_modules/component-tween/examples/rect.html new file mode 100644 index 00000000..84fc4d78 --- /dev/null +++ b/node_modules/component-tween/examples/rect.html @@ -0,0 +1,43 @@ + + + + + + + + \ No newline at end of file diff --git a/node_modules/component-tween/index.js b/node_modules/component-tween/index.js new file mode 100644 index 00000000..229d1f5b --- /dev/null +++ b/node_modules/component-tween/index.js @@ -0,0 +1,178 @@ + +/** + * Module dependencies. + */ + +var Emitter = require('emitter'); +var clone = require('clone'); +var type = require('type'); +var ease = require('ease'); + +/** + * Expose `Tween`. + */ + +module.exports = Tween; + +/** + * Initialize a new `Tween` with `obj`. + * + * @param {Object|Array} obj + * @api public + */ + +function Tween(obj) { + if (!(this instanceof Tween)) return new Tween(obj); + this._from = obj; + this.ease('linear'); + this.duration(500); +} + +/** + * Mixin emitter. + */ + +Emitter(Tween.prototype); + +/** + * Reset the tween. + * + * @api public + */ + +Tween.prototype.reset = function(){ + this.isArray = 'array' === type(this._from); + this._curr = clone(this._from); + this._done = false; + this._start = Date.now(); + return this; +}; + +/** + * Tween to `obj` and reset internal state. + * + * tween.to({ x: 50, y: 100 }) + * + * @param {Object|Array} obj + * @return {Tween} self + * @api public + */ + +Tween.prototype.to = function(obj){ + this.reset(); + this._to = obj; + return this; +}; + +/** + * Set duration to `ms` [500]. + * + * @param {Number} ms + * @return {Tween} self + * @api public + */ + +Tween.prototype.duration = function(ms){ + this._duration = ms; + return this; +}; + +/** + * Set easing function to `fn`. + * + * tween.ease('in-out-sine') + * + * @param {String|Function} fn + * @return {Tween} + * @api public + */ + +Tween.prototype.ease = function(fn){ + fn = 'function' == typeof fn ? fn : ease[fn]; + if (!fn) throw new TypeError('invalid easing function'); + this._ease = fn; + return this; +}; + +/** + * Stop the tween and immediately emit "stop" and "end". + * + * @return {Tween} + * @api public + */ + +Tween.prototype.stop = function(){ + this.stopped = true; + this._done = true; + this.emit('stop'); + this.emit('end'); + return this; +}; + +/** + * Perform a step. + * + * @return {Tween} self + * @api private + */ + +Tween.prototype.step = function(){ + if (this._done) return; + + // duration + var duration = this._duration; + var now = Date.now(); + var delta = now - this._start; + var done = delta >= duration; + + // complete + if (done) { + this._from = this._to; + this._update(this._to); + this._done = true; + this.emit('end'); + return this; + } + + // tween + var from = this._from; + var to = this._to; + var curr = this._curr; + var fn = this._ease; + var p = (now - this._start) / duration; + var n = fn(p); + + // array + if (this.isArray) { + for (var i = 0; i < from.length; ++i) { + curr[i] = from[i] + (to[i] - from[i]) * n; + } + + this._update(curr); + return this; + } + + // objech + for (var k in from) { + curr[k] = from[k] + (to[k] - from[k]) * n; + } + + this._update(curr); + return this; +}; + +/** + * Set update function to `fn` or + * when no argument is given this performs + * a "step". + * + * @param {Function} fn + * @return {Tween} self + * @api public + */ + +Tween.prototype.update = function(fn){ + if (0 == arguments.length) return this.step(); + this._update = fn; + return this; +}; \ No newline at end of file diff --git a/node_modules/component-tween/node_modules/component-emitter/History.md b/node_modules/component-tween/node_modules/component-emitter/History.md new file mode 100644 index 00000000..2ab07791 --- /dev/null +++ b/node_modules/component-tween/node_modules/component-emitter/History.md @@ -0,0 +1,63 @@ + +1.2.0 / 2014-02-12 +================== + + * prefix events with `$` to support object prototype method names + +1.1.3 / 2014-06-20 +================== + + * republish for npm + * add LICENSE file + +1.1.2 / 2014-02-10 +================== + + * package: rename to "component-emitter" + * package: update "main" and "component" fields + * Add license to Readme (same format as the other components) + * created .npmignore + * travis stuff + +1.1.1 / 2013-12-01 +================== + + * fix .once adding .on to the listener + * docs: Emitter#off() + * component: add `.repo` prop + +1.1.0 / 2013-10-20 +================== + + * add `.addEventListener()` and `.removeEventListener()` aliases + +1.0.1 / 2013-06-27 +================== + + * add support for legacy ie + +1.0.0 / 2013-02-26 +================== + + * add `.off()` support for removing all listeners + +0.0.6 / 2012-10-08 +================== + + * add `this._callbacks` initialization to prevent funky gotcha + +0.0.5 / 2012-09-07 +================== + + * fix `Emitter.call(this)` usage + +0.0.3 / 2012-07-11 +================== + + * add `.listeners()` + * rename `.has()` to `.hasListeners()` + +0.0.2 / 2012-06-28 +================== + + * fix `.off()` with `.once()`-registered callbacks diff --git a/node_modules/component-tween/node_modules/component-emitter/LICENSE b/node_modules/component-tween/node_modules/component-emitter/LICENSE new file mode 100644 index 00000000..de516927 --- /dev/null +++ b/node_modules/component-tween/node_modules/component-emitter/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2014 Component contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/component-tween/node_modules/component-emitter/Readme.md b/node_modules/component-tween/node_modules/component-emitter/Readme.md new file mode 100644 index 00000000..0f3f9b9f --- /dev/null +++ b/node_modules/component-tween/node_modules/component-emitter/Readme.md @@ -0,0 +1,74 @@ +# Emitter [![Build Status](https://travis-ci.org/component/emitter.png)](https://travis-ci.org/component/emitter) + + Event emitter component. + +## Installation + +``` +$ component install component/emitter +``` + +## API + +### Emitter(obj) + + The `Emitter` may also be used as a mixin. For example + a "plain" object may become an emitter, or you may + extend an existing prototype. + + As an `Emitter` instance: + +```js +var Emitter = require('emitter'); +var emitter = new Emitter; +emitter.emit('something'); +``` + + As a mixin: + +```js +var Emitter = require('emitter'); +var user = { name: 'tobi' }; +Emitter(user); + +user.emit('im a user'); +``` + + As a prototype mixin: + +```js +var Emitter = require('emitter'); +Emitter(User.prototype); +``` + +### Emitter#on(event, fn) + + Register an `event` handler `fn`. + +### Emitter#once(event, fn) + + Register a single-shot `event` handler `fn`, + removed immediately after it is invoked the + first time. + +### Emitter#off(event, fn) + + * Pass `event` and `fn` to remove a listener. + * Pass `event` to remove all listeners on that event. + * Pass nothing to remove all listeners on all events. + +### Emitter#emit(event, ...) + + Emit an `event` with variable option args. + +### Emitter#listeners(event) + + Return an array of callbacks, or an empty array. + +### Emitter#hasListeners(event) + + Check if this emitter has `event` handlers. + +## License + +MIT diff --git a/node_modules/component-tween/node_modules/component-emitter/index.js b/node_modules/component-tween/node_modules/component-emitter/index.js new file mode 100644 index 00000000..1c781764 --- /dev/null +++ b/node_modules/component-tween/node_modules/component-emitter/index.js @@ -0,0 +1,161 @@ + +/** + * Expose `Emitter`. + */ + +module.exports = Emitter; + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = +Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = +Emitter.prototype.removeListener = +Emitter.prototype.removeAllListeners = +Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks['$' + event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; diff --git a/node_modules/component-tween/node_modules/component-emitter/package.json b/node_modules/component-tween/node_modules/component-emitter/package.json new file mode 100644 index 00000000..b523901e --- /dev/null +++ b/node_modules/component-tween/node_modules/component-emitter/package.json @@ -0,0 +1,24 @@ +{ + "name": "component-emitter", + "description": "Event emitter", + "version": "1.2.0", + "license": "MIT", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "component": { + "scripts": { + "emitter/index.js": "index.js" + } + }, + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/component/emitter.git" + }, + "scripts": { + "test": "make test" + }, + "files": ["index.js", "LICENSE"] +} diff --git a/node_modules/component-tween/package.json b/node_modules/component-tween/package.json new file mode 100644 index 00000000..b198006c --- /dev/null +++ b/node_modules/component-tween/package.json @@ -0,0 +1,32 @@ +{ + "name": "component-tween", + "description": "Motion tween engine using 'ease'", + "version": "1.2.0", + "keywords": [ + "tween", + "tweening", + "animation" + ], + "dependencies": { + "component-clone": "0.2.2", + "component-emitter": "1.2.0", + "component-type": "1.1.0", + "ease-component": "1.0.0" + }, + "browser": { + "clone": "component-clone", + "emitter": "component-emitter", + "type": "component-type", + "ease": "ease-component" + }, + "license": "MIT", + "component": { + "scripts": { + "tween/index.js": "index.js" + } + }, + "repository": { + "type": "git", + "url": "https://github.com/component/tween.git" + } +} diff --git a/node_modules/component-type/.npmignore b/node_modules/component-type/.npmignore new file mode 100644 index 00000000..665aa219 --- /dev/null +++ b/node_modules/component-type/.npmignore @@ -0,0 +1,3 @@ +components +build +node_modules diff --git a/node_modules/component-type/Makefile b/node_modules/component-type/Makefile new file mode 100644 index 00000000..612628a6 --- /dev/null +++ b/node_modules/component-type/Makefile @@ -0,0 +1,14 @@ + +build: components index.js + @component build --dev + +components: + @component install --dev + +clean: + rm -fr build components template.js + +test: + open test/index.html + +.PHONY: clean test diff --git a/node_modules/component-type/Readme.md b/node_modules/component-type/Readme.md new file mode 100644 index 00000000..0b3ceb29 --- /dev/null +++ b/node_modules/component-type/Readme.md @@ -0,0 +1,37 @@ + +# type + + Type assertions aka less-broken `typeof`. + +## Example + +```js +var type = require('type'); + +var obj = new Date; +if (type(obj) == 'date') ... +``` + +## API + +```js +type(new Date) == 'date' +type({}) == 'object' +type(null) == 'null' +type(undefined) == 'undefined' +type("hey") == 'string' +type(true) == 'boolean' +type(false) == 'boolean' +type(12) == 'number' +type(type) == 'function' +type(/asdf/) == 'regexp' +type((function(){ return arguments })()) == 'arguments' +type([]) == 'array' +type(document.createElement('div')) == 'element' +type(NaN) == 'nan' +type(new Error('Ups! Something wrong...')) == 'error' +``` + +## License + + MIT diff --git a/node_modules/component-type/component.json b/node_modules/component-type/component.json new file mode 100644 index 00000000..73ffd651 --- /dev/null +++ b/node_modules/component-type/component.json @@ -0,0 +1,13 @@ +{ + "name": "type", + "description": "Cross-browser type assertions (less broken typeof)", + "version": "1.1.0", + "keywords": ["typeof", "type", "utility"], + "dependencies": {}, + "development": { + "component/assert": "*" + }, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-type/index.js b/node_modules/component-type/index.js new file mode 100644 index 00000000..424c67ba --- /dev/null +++ b/node_modules/component-type/index.js @@ -0,0 +1,34 @@ +/** + * toString ref. + */ + +var toString = Object.prototype.toString; + +/** + * Return the type of `val`. + * + * @param {Mixed} val + * @return {String} + * @api public + */ + +module.exports = function(val){ + switch (toString.call(val)) { + case '[object Date]': return 'date'; + case '[object RegExp]': return 'regexp'; + case '[object Arguments]': return 'arguments'; + case '[object Array]': return 'array'; + case '[object Error]': return 'error'; + } + + if (val === null) return 'null'; + if (val === undefined) return 'undefined'; + if (val !== val) return 'nan'; + if (val && val.nodeType === 1) return 'element'; + + val = val.valueOf + ? val.valueOf() + : Object.prototype.valueOf.apply(val) + + return typeof val; +}; diff --git a/node_modules/component-type/package.json b/node_modules/component-type/package.json new file mode 100644 index 00000000..36083301 --- /dev/null +++ b/node_modules/component-type/package.json @@ -0,0 +1,16 @@ +{ + "name": "component-type", + "description": "Cross-browser type assertions (less broken typeof)", + "version": "1.1.0", + "keywords": [ + "typeof", + "type", + "utility" + ], + "dependencies": {}, + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/component/type.git" + } +} diff --git a/node_modules/component-type/test/index.html b/node_modules/component-type/test/index.html new file mode 100644 index 00000000..9ddb06e2 --- /dev/null +++ b/node_modules/component-type/test/index.html @@ -0,0 +1,17 @@ + + + Mocha + + + + +
    + + + + + + + \ No newline at end of file diff --git a/node_modules/component-type/test/mocha.css b/node_modules/component-type/test/mocha.css new file mode 100644 index 00000000..3b8afb1a --- /dev/null +++ b/node_modules/component-type/test/mocha.css @@ -0,0 +1,231 @@ +@charset "utf-8"; + +body { + font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 60px 50px; +} + +#mocha ul, #mocha li { + margin: 0; + padding: 0; +} + +#mocha ul { + list-style: none; +} + +#mocha h1, #mocha h2 { + margin: 0; +} + +#mocha h1 { + margin-top: 15px; + font-size: 1em; + font-weight: 200; +} + +#mocha h1 a { + text-decoration: none; + color: inherit; +} + +#mocha h1 a:hover { + text-decoration: underline; +} + +#mocha .suite .suite h1 { + margin-top: 0; + font-size: .8em; +} + +.hidden { + display: none; +} + +#mocha h2 { + font-size: 12px; + font-weight: normal; + cursor: pointer; +} + +#mocha .suite { + margin-left: 15px; +} + +#mocha .test { + margin-left: 15px; + overflow: hidden; +} + +#mocha .test.pending:hover h2::after { + content: '(pending)'; + font-family: arial; +} + +#mocha .test.pass.medium .duration { + background: #C09853; +} + +#mocha .test.pass.slow .duration { + background: #B94A48; +} + +#mocha .test.pass::before { + content: '✓'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #00d6b2; +} + +#mocha .test.pass .duration { + font-size: 9px; + margin-left: 5px; + padding: 2px 5px; + color: white; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +#mocha .test.pass.fast .duration { + display: none; +} + +#mocha .test.pending { + color: #0b97c4; +} + +#mocha .test.pending::before { + content: '◦'; + color: #0b97c4; +} + +#mocha .test.fail { + color: #c00; +} + +#mocha .test.fail pre { + color: black; +} + +#mocha .test.fail::before { + content: '✖'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #c00; +} + +#mocha .test pre.error { + color: #c00; + max-height: 300px; + overflow: auto; +} + +#mocha .test pre { + display: block; + float: left; + clear: left; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + border-bottom-color: #ddd; + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px #eee; + -moz-border-radius: 3px; + -moz-box-shadow: 0 1px 3px #eee; +} + +#mocha .test h2 { + position: relative; +} + +#mocha .test a.replay { + position: absolute; + top: 3px; + right: 0; + text-decoration: none; + vertical-align: middle; + display: block; + width: 15px; + height: 15px; + line-height: 15px; + text-align: center; + background: #eee; + font-size: 15px; + -moz-border-radius: 15px; + border-radius: 15px; + -webkit-transition: opacity 200ms; + -moz-transition: opacity 200ms; + transition: opacity 200ms; + opacity: 0.3; + color: #888; +} + +#mocha .test:hover a.replay { + opacity: 1; +} + +#mocha-report.pass .test.fail { + display: none; +} + +#mocha-report.fail .test.pass { + display: none; +} + +#mocha-error { + color: #c00; + font-size: 1.5 em; + font-weight: 100; + letter-spacing: 1px; +} + +#mocha-stats { + position: fixed; + top: 15px; + right: 10px; + font-size: 12px; + margin: 0; + color: #888; +} + +#mocha-stats .progress { + float: right; + padding-top: 0; +} + +#mocha-stats em { + color: black; +} + +#mocha-stats a { + text-decoration: none; + color: inherit; +} + +#mocha-stats a:hover { + border-bottom: 1px solid #eee; +} + +#mocha-stats li { + display: inline-block; + margin: 0 5px; + list-style: none; + padding-top: 11px; +} + +code .comment { color: #ddd } +code .init { color: #2F6FAD } +code .string { color: #5890AD } +code .keyword { color: #8A6343 } +code .number { color: #2F6FAD } diff --git a/node_modules/component-type/test/mocha.js b/node_modules/component-type/test/mocha.js new file mode 100644 index 00000000..2e40cae6 --- /dev/null +++ b/node_modules/component-type/test/mocha.js @@ -0,0 +1,5340 @@ +;(function(){ + + +// CommonJS require() + +function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.charAt(0)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("browser/debug.js", function(module, exports, require){ + +module.exports = function(type){ + return function(){ + + } +}; +}); // module: browser/debug.js + +require.register("browser/diff.js", function(module, exports, require){ +/* See license.txt for terms of usage */ + +/* + * Text diff implementation. + * + * This library supports the following APIS: + * JsDiff.diffChars: Character by character diff + * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace + * JsDiff.diffLines: Line based diff + * + * JsDiff.diffCss: Diff targeted at CSS content + * + * These methods are based on the implementation proposed in + * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 + */ +var JsDiff = (function() { + function clonePath(path) { + return { newPos: path.newPos, components: path.components.slice(0) }; + } + function removeEmpty(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + if (array[i]) { + ret.push(array[i]); + } + } + return ret; + } + function escapeHTML(s) { + var n = s; + n = n.replace(/&/g, "&"); + n = n.replace(//g, ">"); + n = n.replace(/"/g, """); + + return n; + } + + + var fbDiff = function(ignoreWhitespace) { + this.ignoreWhitespace = ignoreWhitespace; + }; + fbDiff.prototype = { + diff: function(oldString, newString) { + // Handle the identity case (this is due to unrolling editLength == 0 + if (newString == oldString) { + return [{ value: newString }]; + } + if (!newString) { + return [{ value: oldString, removed: true }]; + } + if (!oldString) { + return [{ value: newString, added: true }]; + } + + newString = this.tokenize(newString); + oldString = this.tokenize(oldString); + + var newLen = newString.length, oldLen = oldString.length; + var maxEditLength = newLen + oldLen; + var bestPath = [{ newPos: -1, components: [] }]; + + // Seed editLength = 0 + var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); + if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) { + return bestPath[0].components; + } + + for (var editLength = 1; editLength <= maxEditLength; editLength++) { + for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) { + var basePath; + var addPath = bestPath[diagonalPath-1], + removePath = bestPath[diagonalPath+1]; + oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + if (addPath) { + // No one else is going to attempt to use this value, clear it + bestPath[diagonalPath-1] = undefined; + } + + var canAdd = addPath && addPath.newPos+1 < newLen; + var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; + if (!canAdd && !canRemove) { + bestPath[diagonalPath] = undefined; + continue; + } + + // Select the diagonal that we want to branch from. We select the prior + // path whose position in the new string is the farthest from the origin + // and does not pass the bounds of the diff graph + if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { + basePath = clonePath(removePath); + this.pushComponent(basePath.components, oldString[oldPos], undefined, true); + } else { + basePath = clonePath(addPath); + basePath.newPos++; + this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined); + } + + var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath); + + if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) { + return basePath.components; + } else { + bestPath[diagonalPath] = basePath; + } + } + } + }, + + pushComponent: function(components, value, added, removed) { + var last = components[components.length-1]; + if (last && last.added === added && last.removed === removed) { + // We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length-1] = + {value: this.join(last.value, value), added: added, removed: removed }; + } else { + components.push({value: value, added: added, removed: removed }); + } + }, + extractCommon: function(basePath, newString, oldString, diagonalPath) { + var newLen = newString.length, + oldLen = oldString.length, + newPos = basePath.newPos, + oldPos = newPos - diagonalPath; + while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) { + newPos++; + oldPos++; + + this.pushComponent(basePath.components, newString[newPos], undefined, undefined); + } + basePath.newPos = newPos; + return oldPos; + }, + + equals: function(left, right) { + var reWhitespace = /\S/; + if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) { + return true; + } else { + return left == right; + } + }, + join: function(left, right) { + return left + right; + }, + tokenize: function(value) { + return value; + } + }; + + var CharDiff = new fbDiff(); + + var WordDiff = new fbDiff(true); + WordDiff.tokenize = function(value) { + return removeEmpty(value.split(/(\s+|\b)/)); + }; + + var CssDiff = new fbDiff(true); + CssDiff.tokenize = function(value) { + return removeEmpty(value.split(/([{}:;,]|\s+)/)); + }; + + var LineDiff = new fbDiff(); + LineDiff.tokenize = function(value) { + return value.split(/^/m); + }; + + return { + diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); }, + diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); }, + diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); }, + + diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); }, + + createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { + var ret = []; + + ret.push("Index: " + fileName); + ret.push("==================================================================="); + ret.push("--- " + fileName + (typeof oldHeader === "undefined" ? "" : "\t" + oldHeader)); + ret.push("+++ " + fileName + (typeof newHeader === "undefined" ? "" : "\t" + newHeader)); + + var diff = LineDiff.diff(oldStr, newStr); + if (!diff[diff.length-1].value) { + diff.pop(); // Remove trailing newline add + } + diff.push({value: "", lines: []}); // Append an empty value to make cleanup easier + + function contextLines(lines) { + return lines.map(function(entry) { return ' ' + entry; }); + } + function eofNL(curRange, i, current) { + var last = diff[diff.length-2], + isLast = i === diff.length-2, + isLastOfType = i === diff.length-3 && (current.added === !last.added || current.removed === !last.removed); + + // Figure out if this is the last line for the given file and missing NL + if (!/\n$/.test(current.value) && (isLast || isLastOfType)) { + curRange.push('\\ No newline at end of file'); + } + } + + var oldRangeStart = 0, newRangeStart = 0, curRange = [], + oldLine = 1, newLine = 1; + for (var i = 0; i < diff.length; i++) { + var current = diff[i], + lines = current.lines || current.value.replace(/\n$/, "").split("\n"); + current.lines = lines; + + if (current.added || current.removed) { + if (!oldRangeStart) { + var prev = diff[i-1]; + oldRangeStart = oldLine; + newRangeStart = newLine; + + if (prev) { + curRange = contextLines(prev.lines.slice(-4)); + oldRangeStart -= curRange.length; + newRangeStart -= curRange.length; + } + } + curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?"+":"-") + entry; })); + eofNL(curRange, i, current); + + if (current.added) { + newLine += lines.length; + } else { + oldLine += lines.length; + } + } else { + if (oldRangeStart) { + // Close out any changes that have been output (or join overlapping) + if (lines.length <= 8 && i < diff.length-2) { + // Overlapping + curRange.push.apply(curRange, contextLines(lines)); + } else { + // end the range and output + var contextSize = Math.min(lines.length, 4); + ret.push( + "@@ -" + oldRangeStart + "," + (oldLine-oldRangeStart+contextSize) + + " +" + newRangeStart + "," + (newLine-newRangeStart+contextSize) + + " @@"); + ret.push.apply(ret, curRange); + ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); + if (lines.length <= 4) { + eofNL(ret, i, current); + } + + oldRangeStart = 0; newRangeStart = 0; curRange = []; + } + } + oldLine += lines.length; + newLine += lines.length; + } + } + + return ret.join('\n') + '\n'; + }, + + convertChangesToXML: function(changes){ + var ret = []; + for ( var i = 0; i < changes.length; i++) { + var change = changes[i]; + if (change.added) { + ret.push(""); + } else if (change.removed) { + ret.push(""); + } + + ret.push(escapeHTML(change.value)); + + if (change.added) { + ret.push(""); + } else if (change.removed) { + ret.push("
    "); + } + } + return ret.join(""); + } + }; +})(); + +if (typeof module !== "undefined") { + module.exports = JsDiff; +} + +}); // module: browser/diff.js + +require.register("browser/events.js", function(module, exports, require){ + +/** + * Module exports. + */ + +exports.EventEmitter = EventEmitter; + +/** + * Check if `obj` is an array. + */ + +function isArray(obj) { + return '[object Array]' == {}.toString.call(obj); +} + +/** + * Event emitter constructor. + * + * @api public + */ + +function EventEmitter(){}; + +/** + * Adds a listener. + * + * @api public + */ + +EventEmitter.prototype.on = function (name, fn) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = fn; + } else if (isArray(this.$events[name])) { + this.$events[name].push(fn); + } else { + this.$events[name] = [this.$events[name], fn]; + } + + return this; +}; + +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +/** + * Adds a volatile listener. + * + * @api public + */ + +EventEmitter.prototype.once = function (name, fn) { + var self = this; + + function on () { + self.removeListener(name, on); + fn.apply(this, arguments); + }; + + on.listener = fn; + this.on(name, on); + + return this; +}; + +/** + * Removes a listener. + * + * @api public + */ + +EventEmitter.prototype.removeListener = function (name, fn) { + if (this.$events && this.$events[name]) { + var list = this.$events[name]; + + if (isArray(list)) { + var pos = -1; + + for (var i = 0, l = list.length; i < l; i++) { + if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { + pos = i; + break; + } + } + + if (pos < 0) { + return this; + } + + list.splice(pos, 1); + + if (!list.length) { + delete this.$events[name]; + } + } else if (list === fn || (list.listener && list.listener === fn)) { + delete this.$events[name]; + } + } + + return this; +}; + +/** + * Removes all listeners for an event. + * + * @api public + */ + +EventEmitter.prototype.removeAllListeners = function (name) { + if (name === undefined) { + this.$events = {}; + return this; + } + + if (this.$events && this.$events[name]) { + this.$events[name] = null; + } + + return this; +}; + +/** + * Gets all listeners for a certain event. + * + * @api public + */ + +EventEmitter.prototype.listeners = function (name) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = []; + } + + if (!isArray(this.$events[name])) { + this.$events[name] = [this.$events[name]]; + } + + return this.$events[name]; +}; + +/** + * Emits an event. + * + * @api public + */ + +EventEmitter.prototype.emit = function (name) { + if (!this.$events) { + return false; + } + + var handler = this.$events[name]; + + if (!handler) { + return false; + } + + var args = [].slice.call(arguments, 1); + + if ('function' == typeof handler) { + handler.apply(this, args); + } else if (isArray(handler)) { + var listeners = handler.slice(); + + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i].apply(this, args); + } + } else { + return false; + } + + return true; +}; +}); // module: browser/events.js + +require.register("browser/fs.js", function(module, exports, require){ + +}); // module: browser/fs.js + +require.register("browser/path.js", function(module, exports, require){ + +}); // module: browser/path.js + +require.register("browser/progress.js", function(module, exports, require){ + +/** + * Expose `Progress`. + */ + +module.exports = Progress; + +/** + * Initialize a new `Progress` indicator. + */ + +function Progress() { + this.percent = 0; + this.size(0); + this.fontSize(11); + this.font('helvetica, arial, sans-serif'); +} + +/** + * Set progress size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.size = function(n){ + this._size = n; + return this; +}; + +/** + * Set text to `str`. + * + * @param {String} str + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.text = function(str){ + this._text = str; + return this; +}; + +/** + * Set font size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.fontSize = function(n){ + this._fontSize = n; + return this; +}; + +/** + * Set font `family`. + * + * @param {String} family + * @return {Progress} for chaining + */ + +Progress.prototype.font = function(family){ + this._font = family; + return this; +}; + +/** + * Update percentage to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + */ + +Progress.prototype.update = function(n){ + this.percent = n; + return this; +}; + +/** + * Draw on `ctx`. + * + * @param {CanvasRenderingContext2d} ctx + * @return {Progress} for chaining + */ + +Progress.prototype.draw = function(ctx){ + var percent = Math.min(this.percent, 100) + , size = this._size + , half = size / 2 + , x = half + , y = half + , rad = half - 1 + , fontSize = this._fontSize; + + ctx.font = fontSize + 'px ' + this._font; + + var angle = Math.PI * 2 * (percent / 100); + ctx.clearRect(0, 0, size, size); + + // outer circle + ctx.strokeStyle = '#9f9f9f'; + ctx.beginPath(); + ctx.arc(x, y, rad, 0, angle, false); + ctx.stroke(); + + // inner circle + ctx.strokeStyle = '#eee'; + ctx.beginPath(); + ctx.arc(x, y, rad - 1, 0, angle, true); + ctx.stroke(); + + // text + var text = this._text || (percent | 0) + '%' + , w = ctx.measureText(text).width; + + ctx.fillText( + text + , x - w / 2 + 1 + , y + fontSize / 2 - 1); + + return this; +}; + +}); // module: browser/progress.js + +require.register("browser/tty.js", function(module, exports, require){ + +exports.isatty = function(){ + return true; +}; + +exports.getWindowSize = function(){ + return [window.innerHeight, window.innerWidth]; +}; +}); // module: browser/tty.js + +require.register("context.js", function(module, exports, require){ + +/** + * Expose `Context`. + */ + +module.exports = Context; + +/** + * Initialize a new `Context`. + * + * @api private + */ + +function Context(){} + +/** + * Set or get the context `Runnable` to `runnable`. + * + * @param {Runnable} runnable + * @return {Context} + * @api private + */ + +Context.prototype.runnable = function(runnable){ + if (0 == arguments.length) return this._runnable; + this.test = this._runnable = runnable; + return this; +}; + +/** + * Set test timeout `ms`. + * + * @param {Number} ms + * @return {Context} self + * @api private + */ + +Context.prototype.timeout = function(ms){ + this.runnable().timeout(ms); + return this; +}; + +/** + * Set test slowness threshold `ms`. + * + * @param {Number} ms + * @return {Context} self + * @api private + */ + +Context.prototype.slow = function(ms){ + this.runnable().slow(ms); + return this; +}; + +/** + * Inspect the context void of `._runnable`. + * + * @return {String} + * @api private + */ + +Context.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_runnable' == key) return; + if ('test' == key) return; + return val; + }, 2); +}; + +}); // module: context.js + +require.register("hook.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Hook`. + */ + +module.exports = Hook; + +/** + * Initialize a new `Hook` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Hook(title, fn) { + Runnable.call(this, title, fn); + this.type = 'hook'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +function F(){}; +F.prototype = Runnable.prototype; +Hook.prototype = new F; +Hook.prototype.constructor = Hook; + + +/** + * Get or set the test `err`. + * + * @param {Error} err + * @return {Error} + * @api public + */ + +Hook.prototype.error = function(err){ + if (0 == arguments.length) { + var err = this._error; + this._error = null; + return err; + } + + this._error = err; +}; + + +}); // module: hook.js + +require.register("interfaces/bdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * BDD-style interface: + * + * describe('Array', function(){ + * describe('#indexOf()', function(){ + * it('should return -1 when not present', function(){ + * + * }); + * + * it('should return the index when present', function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.describe = context.context = function(title, fn){ + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + fn.call(suite); + suites.shift(); + return suite; + }; + + /** + * Pending describe. + */ + + context.xdescribe = + context.xcontext = + context.describe.skip = function(title, fn){ + var suite = Suite.create(suites[0], title); + suite.pending = true; + suites.unshift(suite); + fn.call(suite); + suites.shift(); + }; + + /** + * Exclusive suite. + */ + + context.describe.only = function(title, fn){ + var suite = context.describe(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.it = context.specify = function(title, fn){ + var suite = suites[0]; + if (suite.pending) var fn = null; + var test = new Test(title, fn); + suite.addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.it.only = function(title, fn){ + var test = context.it(title, fn); + mocha.grep(test.fullTitle()); + }; + + /** + * Pending test case. + */ + + context.xit = + context.xspecify = + context.it.skip = function(title){ + context.it(title); + }; + }); +}; + +}); // module: interfaces/bdd.js + +require.register("interfaces/exports.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * exports.Array = { + * '#indexOf()': { + * 'should return -1 when the value is not present': function(){ + * + * }, + * + * 'should return the correct index when the value is present': function(){ + * + * } + * } + * }; + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('require', visit); + + function visit(obj) { + var suite; + for (var key in obj) { + if ('function' == typeof obj[key]) { + var fn = obj[key]; + switch (key) { + case 'before': + suites[0].beforeAll(fn); + break; + case 'after': + suites[0].afterAll(fn); + break; + case 'beforeEach': + suites[0].beforeEach(fn); + break; + case 'afterEach': + suites[0].afterEach(fn); + break; + default: + suites[0].addTest(new Test(key, fn)); + } + } else { + var suite = Suite.create(suites[0], key); + suites.unshift(suite); + visit(obj[key]); + suites.shift(); + } + } + } +}; +}); // module: interfaces/exports.js + +require.register("interfaces/index.js", function(module, exports, require){ + +exports.bdd = require('./bdd'); +exports.tdd = require('./tdd'); +exports.qunit = require('./qunit'); +exports.exports = require('./exports'); + +}); // module: interfaces/index.js + +require.register("interfaces/qunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * QUnit-style interface: + * + * suite('Array'); + * + * test('#length', function(){ + * var arr = [1,2,3]; + * ok(arr.length == 3); + * }); + * + * test('#indexOf()', function(){ + * var arr = [1,2,3]; + * ok(arr.indexOf(1) == 0); + * ok(arr.indexOf(2) == 1); + * ok(arr.indexOf(3) == 2); + * }); + * + * suite('String'); + * + * test('#length', function(){ + * ok('foo'.length == 3); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title`. + */ + + context.suite = function(title){ + if (suites.length > 1) suites.shift(); + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(title, fn){ + suites[0].addTest(new Test(title, fn)); + }; + }); +}; + +}); // module: interfaces/qunit.js + +require.register("interfaces/tdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * suite('Array', function(){ + * suite('#indexOf()', function(){ + * suiteSetup(function(){ + * + * }); + * + * test('should return -1 when not present', function(){ + * + * }); + * + * test('should return the index when present', function(){ + * + * }); + * + * suiteTeardown(function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before each test case. + */ + + context.setup = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.teardown = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Execute before the suite. + */ + + context.suiteSetup = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after the suite. + */ + + context.suiteTeardown = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.suite = function(title, fn){ + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + fn.call(suite); + suites.shift(); + return suite; + }; + + /** + * Exclusive test-case. + */ + + context.suite.only = function(title, fn){ + var suite = context.suite(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(title, fn){ + var test = new Test(title, fn); + suites[0].addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.test.only = function(title, fn){ + var test = context.test(title, fn); + mocha.grep(test.fullTitle()); + }; + + /** + * Pending test case. + */ + + context.test.skip = function(title){ + context.test(title); + }; + }); +}; + +}); // module: interfaces/tdd.js + +require.register("mocha.js", function(module, exports, require){ +/*! + * mocha + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var path = require('browser/path') + , utils = require('./utils'); + +/** + * Expose `Mocha`. + */ + +exports = module.exports = Mocha; + +/** + * Expose internals. + */ + +exports.utils = utils; +exports.interfaces = require('./interfaces'); +exports.reporters = require('./reporters'); +exports.Runnable = require('./runnable'); +exports.Context = require('./context'); +exports.Runner = require('./runner'); +exports.Suite = require('./suite'); +exports.Hook = require('./hook'); +exports.Test = require('./test'); + +/** + * Return image `name` path. + * + * @param {String} name + * @return {String} + * @api private + */ + +function image(name) { + return __dirname + '/../images/' + name + '.png'; +} + +/** + * Setup mocha with `options`. + * + * Options: + * + * - `ui` name "bdd", "tdd", "exports" etc + * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` + * - `globals` array of accepted globals + * - `timeout` timeout in milliseconds + * - `bail` bail on the first test failure + * - `slow` milliseconds to wait before considering a test slow + * - `ignoreLeaks` ignore global leaks + * - `grep` string or regexp to filter tests with + * + * @param {Object} options + * @api public + */ + +function Mocha(options) { + options = options || {}; + this.files = []; + this.options = options; + this.grep(options.grep); + this.suite = new exports.Suite('', new exports.Context); + this.ui(options.ui); + this.bail(options.bail); + this.reporter(options.reporter); + if (options.timeout) this.timeout(options.timeout); + if (options.slow) this.slow(options.slow); +} + +/** + * Enable or disable bailing on the first failure. + * + * @param {Boolean} [bail] + * @api public + */ + +Mocha.prototype.bail = function(bail){ + if (0 == arguments.length) bail = true; + this.suite.bail(bail); + return this; +}; + +/** + * Add test `file`. + * + * @param {String} file + * @api public + */ + +Mocha.prototype.addFile = function(file){ + this.files.push(file); + return this; +}; + +/** + * Set reporter to `reporter`, defaults to "dot". + * + * @param {String|Function} reporter name or constructor + * @api public + */ + +Mocha.prototype.reporter = function(reporter){ + if ('function' == typeof reporter) { + this._reporter = reporter; + } else { + reporter = reporter || 'dot'; + try { + this._reporter = require('./reporters/' + reporter); + } catch (err) { + this._reporter = require(reporter); + } + if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"'); + } + return this; +}; + +/** + * Set test UI `name`, defaults to "bdd". + * + * @param {String} bdd + * @api public + */ + +Mocha.prototype.ui = function(name){ + name = name || 'bdd'; + this._ui = exports.interfaces[name]; + if (!this._ui) throw new Error('invalid interface "' + name + '"'); + this._ui = this._ui(this.suite); + return this; +}; + +/** + * Load registered files. + * + * @api private + */ + +Mocha.prototype.loadFiles = function(fn){ + var self = this; + var suite = this.suite; + var pending = this.files.length; + this.files.forEach(function(file){ + file = path.resolve(file); + suite.emit('pre-require', global, file, self); + suite.emit('require', require(file), file, self); + suite.emit('post-require', global, file, self); + --pending || (fn && fn()); + }); +}; + +/** + * Enable growl support. + * + * @api private + */ + +Mocha.prototype._growl = function(runner, reporter) { + var notify = require('growl'); + + runner.on('end', function(){ + var stats = reporter.stats; + if (stats.failures) { + var msg = stats.failures + ' of ' + runner.total + ' tests failed'; + notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); + } else { + notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { + name: 'mocha' + , title: 'Passed' + , image: image('ok') + }); + } + }); +}; + +/** + * Add regexp to grep, if `re` is a string it is escaped. + * + * @param {RegExp|String} re + * @return {Mocha} + * @api public + */ + +Mocha.prototype.grep = function(re){ + this.options.grep = 'string' == typeof re + ? new RegExp(utils.escapeRegexp(re)) + : re; + return this; +}; + +/** + * Invert `.grep()` matches. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.invert = function(){ + this.options.invert = true; + return this; +}; + +/** + * Ignore global leaks. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.ignoreLeaks = function(){ + this.options.ignoreLeaks = true; + return this; +}; + +/** + * Enable global leak checking. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.checkLeaks = function(){ + this.options.ignoreLeaks = false; + return this; +}; + +/** + * Enable growl support. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.growl = function(){ + this.options.growl = true; + return this; +}; + +/** + * Ignore `globals` array or string. + * + * @param {Array|String} globals + * @return {Mocha} + * @api public + */ + +Mocha.prototype.globals = function(globals){ + this.options.globals = (this.options.globals || []).concat(globals); + return this; +}; + +/** + * Set the timeout in milliseconds. + * + * @param {Number} timeout + * @return {Mocha} + * @api public + */ + +Mocha.prototype.timeout = function(timeout){ + this.suite.timeout(timeout); + return this; +}; + +/** + * Set slowness threshold in milliseconds. + * + * @param {Number} slow + * @return {Mocha} + * @api public + */ + +Mocha.prototype.slow = function(slow){ + this.suite.slow(slow); + return this; +}; + +/** + * Makes all tests async (accepting a callback) + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.asyncOnly = function(){ + this.options.asyncOnly = true; + return this; +}; + +/** + * Run tests and invoke `fn()` when complete. + * + * @param {Function} fn + * @return {Runner} + * @api public + */ + +Mocha.prototype.run = function(fn){ + if (this.files.length) this.loadFiles(); + var suite = this.suite; + var options = this.options; + var runner = new exports.Runner(suite); + var reporter = new this._reporter(runner); + runner.ignoreLeaks = options.ignoreLeaks; + runner.asyncOnly = options.asyncOnly; + if (options.grep) runner.grep(options.grep, options.invert); + if (options.globals) runner.globals(options.globals); + if (options.growl) this._growl(runner, reporter); + return runner.run(fn); +}; + +}); // module: mocha.js + +require.register("ms.js", function(module, exports, require){ + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; + +/** + * Parse or format the given `val`. + * + * @param {String|Number} val + * @return {String|Number} + * @api public + */ + +module.exports = function(val){ + if ('string' == typeof val) return parse(val); + return format(val); +} + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); + if (!m) return; + var n = parseFloat(m[1]); + var type = (m[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'y': + return n * 31557600000; + case 'days': + case 'day': + case 'd': + return n * 86400000; + case 'hours': + case 'hour': + case 'h': + return n * 3600000; + case 'minutes': + case 'minute': + case 'm': + return n * 60000; + case 'seconds': + case 'second': + case 's': + return n * 1000; + case 'ms': + return n; + } +} + +/** + * Format the given `ms`. + * + * @param {Number} ms + * @return {String} + * @api public + */ + +function format(ms) { + if (ms == d) return Math.round(ms / d) + ' day'; + if (ms > d) return Math.round(ms / d) + ' days'; + if (ms == h) return Math.round(ms / h) + ' hour'; + if (ms > h) return Math.round(ms / h) + ' hours'; + if (ms == m) return Math.round(ms / m) + ' minute'; + if (ms > m) return Math.round(ms / m) + ' minutes'; + if (ms == s) return Math.round(ms / s) + ' second'; + if (ms > s) return Math.round(ms / s) + ' seconds'; + return ms + ' ms'; +} +}); // module: ms.js + +require.register("reporters/base.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var tty = require('browser/tty') + , diff = require('browser/diff') + , ms = require('../ms'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Check if both stdio streams are associated with a tty. + */ + +var isatty = tty.isatty(1) && tty.isatty(2); + +/** + * Expose `Base`. + */ + +exports = module.exports = Base; + +/** + * Enable coloring by default. + */ + +exports.useColors = isatty; + +/** + * Default color map. + */ + +exports.colors = { + 'pass': 90 + , 'fail': 31 + , 'bright pass': 92 + , 'bright fail': 91 + , 'bright yellow': 93 + , 'pending': 36 + , 'suite': 0 + , 'error title': 0 + , 'error message': 31 + , 'error stack': 90 + , 'checkmark': 32 + , 'fast': 90 + , 'medium': 33 + , 'slow': 31 + , 'green': 32 + , 'light': 90 + , 'diff gutter': 90 + , 'diff added': 42 + , 'diff removed': 41 +}; + +/** + * Default symbol map. + */ + +exports.symbols = { + ok: '✓', + err: '✖', + dot: '․' +}; + +// With node.js on Windows: use symbols available in terminal default fonts +if ('win32' == process.platform) { + exports.symbols.ok = '\u221A'; + exports.symbols.err = '\u00D7'; + exports.symbols.dot = '.'; +} + +/** + * Color `str` with the given `type`, + * allowing colors to be disabled, + * as well as user-defined color + * schemes. + * + * @param {String} type + * @param {String} str + * @return {String} + * @api private + */ + +var color = exports.color = function(type, str) { + if (!exports.useColors) return str; + return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; +}; + +/** + * Expose term window size, with some + * defaults for when stderr is not a tty. + */ + +exports.window = { + width: isatty + ? process.stdout.getWindowSize + ? process.stdout.getWindowSize(1)[0] + : tty.getWindowSize()[1] + : 75 +}; + +/** + * Expose some basic cursor interactions + * that are common among reporters. + */ + +exports.cursor = { + hide: function(){ + process.stdout.write('\u001b[?25l'); + }, + + show: function(){ + process.stdout.write('\u001b[?25h'); + }, + + deleteLine: function(){ + process.stdout.write('\u001b[2K'); + }, + + beginningOfLine: function(){ + process.stdout.write('\u001b[0G'); + }, + + CR: function(){ + exports.cursor.deleteLine(); + exports.cursor.beginningOfLine(); + } +}; + +/** + * Outut the given `failures` as a list. + * + * @param {Array} failures + * @api public + */ + +exports.list = function(failures){ + console.error(); + failures.forEach(function(test, i){ + // format + var fmt = color('error title', ' %s) %s:\n') + + color('error message', ' %s') + + color('error stack', '\n%s\n'); + + // msg + var err = test.err + , message = err.message || '' + , stack = err.stack || message + , index = stack.indexOf(message) + message.length + , msg = stack.slice(0, index) + , actual = err.actual + , expected = err.expected + , escape = true; + + // explicitly show diff + if (err.showDiff) { + escape = false; + err.actual = actual = JSON.stringify(actual, null, 2); + err.expected = expected = JSON.stringify(expected, null, 2); + } + + // actual / expected diff + if ('string' == typeof actual && 'string' == typeof expected) { + var len = Math.max(actual.length, expected.length); + + if (len < 20) msg = errorDiff(err, 'Chars', escape); + else msg = errorDiff(err, 'Words', escape); + + // linenos + var lines = msg.split('\n'); + if (lines.length > 4) { + var width = String(lines.length).length; + msg = lines.map(function(str, i){ + return pad(++i, width) + ' |' + ' ' + str; + }).join('\n'); + } + + // legend + msg = '\n' + + color('diff removed', 'actual') + + ' ' + + color('diff added', 'expected') + + '\n\n' + + msg + + '\n'; + + // indent + msg = msg.replace(/^/gm, ' '); + + fmt = color('error title', ' %s) %s:\n%s') + + color('error stack', '\n%s\n'); + } + + // indent stack trace without msg + stack = stack.slice(index ? index + 1 : index) + .replace(/^/gm, ' '); + + console.error(fmt, (i + 1), test.fullTitle(), msg, stack); + }); +}; + +/** + * Initialize a new `Base` reporter. + * + * All other reporters generally + * inherit from this reporter, providing + * stats such as test duration, number + * of tests passed / failed etc. + * + * @param {Runner} runner + * @api public + */ + +function Base(runner) { + var self = this + , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } + , failures = this.failures = []; + + if (!runner) return; + this.runner = runner; + + runner.stats = stats; + + runner.on('start', function(){ + stats.start = new Date; + }); + + runner.on('suite', function(suite){ + stats.suites = stats.suites || 0; + suite.root || stats.suites++; + }); + + runner.on('test end', function(test){ + stats.tests = stats.tests || 0; + stats.tests++; + }); + + runner.on('pass', function(test){ + stats.passes = stats.passes || 0; + + var medium = test.slow() / 2; + test.speed = test.duration > test.slow() + ? 'slow' + : test.duration > medium + ? 'medium' + : 'fast'; + + stats.passes++; + }); + + runner.on('fail', function(test, err){ + stats.failures = stats.failures || 0; + stats.failures++; + test.err = err; + failures.push(test); + }); + + runner.on('end', function(){ + stats.end = new Date; + stats.duration = new Date - stats.start; + }); + + runner.on('pending', function(){ + stats.pending++; + }); +} + +/** + * Output common epilogue used by many of + * the bundled reporters. + * + * @api public + */ + +Base.prototype.epilogue = function(){ + var stats = this.stats + , fmt + , tests; + + console.log(); + + function pluralize(n) { + return 1 == n ? 'test' : 'tests'; + } + + // failure + if (stats.failures) { + fmt = color('bright fail', ' ' + exports.symbols.err) + + color('fail', ' %d of %d %s failed') + + color('light', ':') + + console.error(fmt, + stats.failures, + this.runner.total, + pluralize(this.runner.total)); + + Base.list(this.failures); + console.error(); + return; + } + + // pass + fmt = color('bright pass', ' ') + + color('green', ' %d %s complete') + + color('light', ' (%s)'); + + console.log(fmt, + stats.tests || 0, + pluralize(stats.tests), + ms(stats.duration)); + + // pending + if (stats.pending) { + fmt = color('pending', ' ') + + color('pending', ' %d %s pending'); + + console.log(fmt, stats.pending, pluralize(stats.pending)); + } + + console.log(); +}; + +/** + * Pad the given `str` to `len`. + * + * @param {String} str + * @param {String} len + * @return {String} + * @api private + */ + +function pad(str, len) { + str = String(str); + return Array(len - str.length + 1).join(' ') + str; +} + +/** + * Return a character diff for `err`. + * + * @param {Error} err + * @return {String} + * @api private + */ + +function errorDiff(err, type, escape) { + return diff['diff' + type](err.actual, err.expected).map(function(str){ + if (escape) { + str.value = str.value + .replace(/\t/g, '') + .replace(/\r/g, '') + .replace(/\n/g, '\n'); + } + if (str.added) return colorLines('diff added', str.value); + if (str.removed) return colorLines('diff removed', str.value); + return str.value; + }).join(''); +} + +/** + * Color lines for `str`, using the color `name`. + * + * @param {String} name + * @param {String} str + * @return {String} + * @api private + */ + +function colorLines(name, str) { + return str.split('\n').map(function(str){ + return color(name, str); + }).join('\n'); +} + +}); // module: reporters/base.js + +require.register("reporters/doc.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Doc`. + */ + +exports = module.exports = Doc; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Doc(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , indents = 2; + + function indent() { + return Array(indents).join(' '); + } + + runner.on('suite', function(suite){ + if (suite.root) return; + ++indents; + console.log('%s
    ', indent()); + ++indents; + console.log('%s

    %s

    ', indent(), utils.escape(suite.title)); + console.log('%s
    ', indent()); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + console.log('%s
    ', indent()); + --indents; + console.log('%s
    ', indent()); + --indents; + }); + + runner.on('pass', function(test){ + console.log('%s
    %s
    ', indent(), utils.escape(test.title)); + var code = utils.escape(utils.clean(test.fn.toString())); + console.log('%s
    %s
    ', indent(), code); + }); +} + +}); // module: reporters/doc.js + +require.register("reporters/dot.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = Dot; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Dot(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , n = 0; + + runner.on('start', function(){ + process.stdout.write('\n '); + }); + + runner.on('pending', function(test){ + process.stdout.write(color('pending', Base.symbols.dot)); + }); + + runner.on('pass', function(test){ + if (++n % width == 0) process.stdout.write('\n '); + if ('slow' == test.speed) { + process.stdout.write(color('bright yellow', Base.symbols.dot)); + } else { + process.stdout.write(color(test.speed, Base.symbols.dot)); + } + }); + + runner.on('fail', function(test, err){ + if (++n % width == 0) process.stdout.write('\n '); + process.stdout.write(color('fail', Base.symbols.dot)); + }); + + runner.on('end', function(){ + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +Dot.prototype = new F; +Dot.prototype.constructor = Dot; + +}); // module: reporters/dot.js + +require.register("reporters/html-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var JSONCov = require('./json-cov') + , fs = require('browser/fs'); + +/** + * Expose `HTMLCov`. + */ + +exports = module.exports = HTMLCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTMLCov(runner) { + var jade = require('jade') + , file = __dirname + '/templates/coverage.jade' + , str = fs.readFileSync(file, 'utf8') + , fn = jade.compile(str, { filename: file }) + , self = this; + + JSONCov.call(this, runner, false); + + runner.on('end', function(){ + process.stdout.write(fn({ + cov: self.cov + , coverageClass: coverageClass + })); + }); +} + +/** + * Return coverage class for `n`. + * + * @return {String} + * @api private + */ + +function coverageClass(n) { + if (n >= 75) return 'high'; + if (n >= 50) return 'medium'; + if (n >= 25) return 'low'; + return 'terrible'; +} +}); // module: reporters/html-cov.js + +require.register("reporters/html.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , Progress = require('../browser/progress') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `Doc`. + */ + +exports = module.exports = HTML; + +/** + * Stats template. + */ + +var statsTemplate = '
    '; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTML(runner, root) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , stat = fragment(statsTemplate) + , items = stat.getElementsByTagName('li') + , passes = items[1].getElementsByTagName('em')[0] + , passesLink = items[1].getElementsByTagName('a')[0] + , failures = items[2].getElementsByTagName('em')[0] + , failuresLink = items[2].getElementsByTagName('a')[0] + , duration = items[3].getElementsByTagName('em')[0] + , canvas = stat.getElementsByTagName('canvas')[0] + , report = fragment('
      ') + , stack = [report] + , progress + , ctx + + root = root || document.getElementById('mocha'); + + if (canvas.getContext) { + var ratio = window.devicePixelRatio || 1; + canvas.style.width = canvas.width; + canvas.style.height = canvas.height; + canvas.width *= ratio; + canvas.height *= ratio; + ctx = canvas.getContext('2d'); + ctx.scale(ratio, ratio); + progress = new Progress; + } + + if (!root) return error('#mocha div missing, add it to your document'); + + // pass toggle + on(passesLink, 'click', function(){ + unhide(); + var name = /pass/.test(report.className) ? '' : ' pass'; + report.className = report.className.replace(/fail|pass/g, '') + name; + if (report.className.trim()) hideSuitesWithout('test pass'); + }); + + // failure toggle + on(failuresLink, 'click', function(){ + unhide(); + var name = /fail/.test(report.className) ? '' : ' fail'; + report.className = report.className.replace(/fail|pass/g, '') + name; + if (report.className.trim()) hideSuitesWithout('test fail'); + }); + + root.appendChild(stat); + root.appendChild(report); + + if (progress) progress.size(40); + + runner.on('suite', function(suite){ + if (suite.root) return; + + // suite + var url = '?grep=' + encodeURIComponent(suite.fullTitle()); + var el = fragment('
    • %s

    • ', url, escape(suite.title)); + + // container + stack[0].appendChild(el); + stack.unshift(document.createElement('ul')); + el.appendChild(stack[0]); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + stack.shift(); + }); + + runner.on('fail', function(test, err){ + if ('hook' == test.type) runner.emit('test end', test); + }); + + runner.on('test end', function(test){ + window.scrollTo(0, document.body.scrollHeight); + + // TODO: add to stats + var percent = stats.tests / this.total * 100 | 0; + if (progress) progress.update(percent).draw(ctx); + + // update stats + var ms = new Date - stats.start; + text(passes, stats.passes); + text(failures, stats.failures); + text(duration, (ms / 1000).toFixed(2)); + + // test + if ('passed' == test.state) { + var el = fragment('
    • %e%ems ‣

    • ', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle())); + } else if (test.pending) { + var el = fragment('
    • %e

    • ', test.title); + } else { + var el = fragment('
    • %e ‣

    • ', test.title, encodeURIComponent(test.fullTitle())); + var str = test.err.stack || test.err.toString(); + + // FF / Opera do not add the message + if (!~str.indexOf(test.err.message)) { + str = test.err.message + '\n' + str; + } + + // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we + // check for the result of the stringifying. + if ('[object Error]' == str) str = test.err.message; + + // Safari doesn't give you a stack. Let's at least provide a source line. + if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { + str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; + } + + el.appendChild(fragment('
      %e
      ', str)); + } + + // toggle code + // TODO: defer + if (!test.pending) { + var h2 = el.getElementsByTagName('h2')[0]; + + on(h2, 'click', function(){ + pre.style.display = 'none' == pre.style.display + ? 'block' + : 'none'; + }); + + var pre = fragment('
      %e
      ', utils.clean(test.fn.toString())); + el.appendChild(pre); + pre.style.display = 'none'; + } + + // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack. + if (stack[0]) stack[0].appendChild(el); + }); +} + +/** + * Display error `msg`. + */ + +function error(msg) { + document.body.appendChild(fragment('
      %s
      ', msg)); +} + +/** + * Return a DOM fragment from `html`. + */ + +function fragment(html) { + var args = arguments + , div = document.createElement('div') + , i = 1; + + div.innerHTML = html.replace(/%([se])/g, function(_, type){ + switch (type) { + case 's': return String(args[i++]); + case 'e': return escape(args[i++]); + } + }); + + return div.firstChild; +} + +/** + * Check for suites that do not have elements + * with `classname`, and hide them. + */ + +function hideSuitesWithout(classname) { + var suites = document.getElementsByClassName('suite'); + for (var i = 0; i < suites.length; i++) { + var els = suites[i].getElementsByClassName(classname); + if (0 == els.length) suites[i].className += ' hidden'; + } +} + +/** + * Unhide .hidden suites. + */ + +function unhide() { + var els = document.getElementsByClassName('suite hidden'); + for (var i = 0; i < els.length; ++i) { + els[i].className = els[i].className.replace('suite hidden', 'suite'); + } +} + +/** + * Set `el` text to `str`. + */ + +function text(el, str) { + if (el.textContent) { + el.textContent = str; + } else { + el.innerText = str; + } +} + +/** + * Listen on `event` with callback `fn`. + */ + +function on(el, event, fn) { + if (el.addEventListener) { + el.addEventListener(event, fn, false); + } else { + el.attachEvent('on' + event, fn); + } +} + +}); // module: reporters/html.js + +require.register("reporters/index.js", function(module, exports, require){ + +exports.Base = require('./base'); +exports.Dot = require('./dot'); +exports.Doc = require('./doc'); +exports.TAP = require('./tap'); +exports.JSON = require('./json'); +exports.HTML = require('./html'); +exports.List = require('./list'); +exports.Min = require('./min'); +exports.Spec = require('./spec'); +exports.Nyan = require('./nyan'); +exports.XUnit = require('./xunit'); +exports.Markdown = require('./markdown'); +exports.Progress = require('./progress'); +exports.Landing = require('./landing'); +exports.JSONCov = require('./json-cov'); +exports.HTMLCov = require('./html-cov'); +exports.JSONStream = require('./json-stream'); +exports.Teamcity = require('./teamcity'); + +}); // module: reporters/index.js + +require.register("reporters/json-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `JSONCov`. + */ + +exports = module.exports = JSONCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @param {Boolean} output + * @api public + */ + +function JSONCov(runner, output) { + var self = this + , output = 1 == arguments.length ? true : output; + + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var cov = global._$jscoverage || {}; + var result = self.cov = map(cov); + result.stats = self.stats; + result.tests = tests.map(clean); + result.failures = failures.map(clean); + result.passes = passes.map(clean); + if (!output) return; + process.stdout.write(JSON.stringify(result, null, 2 )); + }); +} + +/** + * Map jscoverage data to a JSON structure + * suitable for reporting. + * + * @param {Object} cov + * @return {Object} + * @api private + */ + +function map(cov) { + var ret = { + instrumentation: 'node-jscoverage' + , sloc: 0 + , hits: 0 + , misses: 0 + , coverage: 0 + , files: [] + }; + + for (var filename in cov) { + var data = coverage(filename, cov[filename]); + ret.files.push(data); + ret.hits += data.hits; + ret.misses += data.misses; + ret.sloc += data.sloc; + } + + ret.files.sort(function(a, b) { + return a.filename.localeCompare(b.filename); + }); + + if (ret.sloc > 0) { + ret.coverage = (ret.hits / ret.sloc) * 100; + } + + return ret; +}; + +/** + * Map jscoverage data for a single source file + * to a JSON structure suitable for reporting. + * + * @param {String} filename name of the source file + * @param {Object} data jscoverage coverage data + * @return {Object} + * @api private + */ + +function coverage(filename, data) { + var ret = { + filename: filename, + coverage: 0, + hits: 0, + misses: 0, + sloc: 0, + source: {} + }; + + data.source.forEach(function(line, num){ + num++; + + if (data[num] === 0) { + ret.misses++; + ret.sloc++; + } else if (data[num] !== undefined) { + ret.hits++; + ret.sloc++; + } + + ret.source[num] = { + source: line + , coverage: data[num] === undefined + ? '' + : data[num] + }; + }); + + ret.coverage = ret.hits / ret.sloc * 100; + + return ret; +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} + +}); // module: reporters/json-cov.js + +require.register("reporters/json-stream.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total; + + runner.on('start', function(){ + console.log(JSON.stringify(['start', { total: total }])); + }); + + runner.on('pass', function(test){ + console.log(JSON.stringify(['pass', clean(test)])); + }); + + runner.on('fail', function(test, err){ + console.log(JSON.stringify(['fail', clean(test)])); + }); + + runner.on('end', function(){ + process.stdout.write(JSON.stringify(['end', self.stats])); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json-stream.js + +require.register("reporters/json.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `JSON`. + */ + +exports = module.exports = JSONReporter; + +/** + * Initialize a new `JSON` reporter. + * + * @param {Runner} runner + * @api public + */ + +function JSONReporter(runner) { + var self = this; + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var obj = { + stats: self.stats + , tests: tests.map(clean) + , failures: failures.map(clean) + , passes: passes.map(clean) + }; + + process.stdout.write(JSON.stringify(obj, null, 2)); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json.js + +require.register("reporters/landing.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Landing`. + */ + +exports = module.exports = Landing; + +/** + * Airplane color. + */ + +Base.colors.plane = 0; + +/** + * Airplane crash color. + */ + +Base.colors['plane crash'] = 31; + +/** + * Runway color. + */ + +Base.colors.runway = 90; + +/** + * Initialize a new `Landing` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Landing(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , total = runner.total + , stream = process.stdout + , plane = color('plane', '✈') + , crashed = -1 + , n = 0; + + function runway() { + var buf = Array(width).join('-'); + return ' ' + color('runway', buf); + } + + runner.on('start', function(){ + stream.write('\n '); + cursor.hide(); + }); + + runner.on('test end', function(test){ + // check if the plane crashed + var col = -1 == crashed + ? width * ++n / total | 0 + : crashed; + + // show the crash + if ('failed' == test.state) { + plane = color('plane crash', '✈'); + crashed = col; + } + + // render landing strip + stream.write('\u001b[4F\n\n'); + stream.write(runway()); + stream.write('\n '); + stream.write(color('runway', Array(col).join('⋅'))); + stream.write(plane) + stream.write(color('runway', Array(width - col).join('⋅') + '\n')); + stream.write(runway()); + stream.write('\u001b[0m'); + }); + + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +Landing.prototype = new F; +Landing.prototype.constructor = Landing; + +}); // module: reporters/landing.js + +require.register("reporters/list.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , n = 0; + + runner.on('start', function(){ + console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = color('checkmark', ' -') + + color('pending', ' %s'); + console.log(fmt, test.fullTitle()); + }); + + runner.on('pass', function(test){ + var fmt = color('checkmark', ' '+Base.symbols.dot) + + color('pass', ' %s: ') + + color(test.speed, '%dms'); + cursor.CR(); + console.log(fmt, test.fullTitle(), test.duration); + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +List.prototype = new F; +List.prototype.constructor = List; + + +}); // module: reporters/list.js + +require.register("reporters/markdown.js", function(module, exports, require){ +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Markdown`. + */ + +exports = module.exports = Markdown; + +/** + * Initialize a new `Markdown` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Markdown(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , level = 0 + , buf = ''; + + function title(str) { + return Array(level).join('#') + ' ' + str; + } + + function indent() { + return Array(level).join(' '); + } + + function mapTOC(suite, obj) { + var ret = obj; + obj = obj[suite.title] = obj[suite.title] || { suite: suite }; + suite.suites.forEach(function(suite){ + mapTOC(suite, obj); + }); + return ret; + } + + function stringifyTOC(obj, level) { + ++level; + var buf = ''; + var link; + for (var key in obj) { + if ('suite' == key) continue; + if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; + if (key) buf += Array(level).join(' ') + link; + buf += stringifyTOC(obj[key], level); + } + --level; + return buf; + } + + function generateTOC(suite) { + var obj = mapTOC(suite, {}); + return stringifyTOC(obj, 0); + } + + generateTOC(runner.suite); + + runner.on('suite', function(suite){ + ++level; + var slug = utils.slug(suite.fullTitle()); + buf += '' + '\n'; + buf += title(suite.title) + '\n'; + }); + + runner.on('suite end', function(suite){ + --level; + }); + + runner.on('pass', function(test){ + var code = utils.clean(test.fn.toString()); + buf += test.title + '.\n'; + buf += '\n```js\n'; + buf += code + '\n'; + buf += '```\n\n'; + }); + + runner.on('end', function(){ + process.stdout.write('# TOC\n'); + process.stdout.write(generateTOC(runner.suite)); + process.stdout.write(buf); + }); +} +}); // module: reporters/markdown.js + +require.register("reporters/min.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Min`. + */ + +exports = module.exports = Min; + +/** + * Initialize a new `Min` minimal test reporter (best used with --watch). + * + * @param {Runner} runner + * @api public + */ + +function Min(runner) { + Base.call(this, runner); + + runner.on('start', function(){ + // clear screen + process.stdout.write('\u001b[2J'); + // set cursor position + process.stdout.write('\u001b[1;3H'); + }); + + runner.on('end', this.epilogue.bind(this)); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +Min.prototype = new F; +Min.prototype.constructor = Min; + +}); // module: reporters/min.js + +require.register("reporters/nyan.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = NyanCat; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function NyanCat(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , rainbowColors = this.rainbowColors = self.generateColors() + , colorIndex = this.colorIndex = 0 + , numerOfLines = this.numberOfLines = 4 + , trajectories = this.trajectories = [[], [], [], []] + , nyanCatWidth = this.nyanCatWidth = 11 + , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) + , scoreboardWidth = this.scoreboardWidth = 5 + , tick = this.tick = 0 + , n = 0; + + runner.on('start', function(){ + Base.cursor.hide(); + self.draw('start'); + }); + + runner.on('pending', function(test){ + self.draw('pending'); + }); + + runner.on('pass', function(test){ + self.draw('pass'); + }); + + runner.on('fail', function(test, err){ + self.draw('fail'); + }); + + runner.on('end', function(){ + Base.cursor.show(); + for (var i = 0; i < self.numberOfLines; i++) write('\n'); + self.epilogue(); + }); +} + +/** + * Draw the nyan cat with runner `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.draw = function(status){ + this.appendRainbow(); + this.drawScoreboard(); + this.drawRainbow(); + this.drawNyanCat(status); + this.tick = !this.tick; +}; + +/** + * Draw the "scoreboard" showing the number + * of passes, failures and pending tests. + * + * @api private + */ + +NyanCat.prototype.drawScoreboard = function(){ + var stats = this.stats; + var colors = Base.colors; + + function draw(color, n) { + write(' '); + write('\u001b[' + color + 'm' + n + '\u001b[0m'); + write('\n'); + } + + draw(colors.green, stats.passes); + draw(colors.fail, stats.failures); + draw(colors.pending, stats.pending); + write('\n'); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Append the rainbow. + * + * @api private + */ + +NyanCat.prototype.appendRainbow = function(){ + var segment = this.tick ? '_' : '-'; + var rainbowified = this.rainbowify(segment); + + for (var index = 0; index < this.numberOfLines; index++) { + var trajectory = this.trajectories[index]; + if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); + trajectory.push(rainbowified); + } +}; + +/** + * Draw the rainbow. + * + * @api private + */ + +NyanCat.prototype.drawRainbow = function(){ + var self = this; + + this.trajectories.forEach(function(line, index) { + write('\u001b[' + self.scoreboardWidth + 'C'); + write(line.join('')); + write('\n'); + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Draw the nyan cat with `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.drawNyanCat = function(status) { + var self = this; + var startWidth = this.scoreboardWidth + this.trajectories[0].length; + + [0, 1, 2, 3].forEach(function(index) { + write('\u001b[' + startWidth + 'C'); + + switch (index) { + case 0: + write('_,------,'); + write('\n'); + break; + case 1: + var padding = self.tick ? ' ' : ' '; + write('_|' + padding + '/\\_/\\ '); + write('\n'); + break; + case 2: + var padding = self.tick ? '_' : '__'; + var tail = self.tick ? '~' : '^'; + var face; + switch (status) { + case 'pass': + face = '( ^ .^)'; + break; + case 'fail': + face = '( o .o)'; + break; + default: + face = '( - .-)'; + } + write(tail + '|' + padding + face + ' '); + write('\n'); + break; + case 3: + var padding = self.tick ? ' ' : ' '; + write(padding + '"" "" '); + write('\n'); + break; + } + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Move cursor up `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorUp = function(n) { + write('\u001b[' + n + 'A'); +}; + +/** + * Move cursor down `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorDown = function(n) { + write('\u001b[' + n + 'B'); +}; + +/** + * Generate rainbow colors. + * + * @return {Array} + * @api private + */ + +NyanCat.prototype.generateColors = function(){ + var colors = []; + + for (var i = 0; i < (6 * 7); i++) { + var pi3 = Math.floor(Math.PI / 3); + var n = (i * (1.0 / 6)); + var r = Math.floor(3 * Math.sin(n) + 3); + var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); + var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); + colors.push(36 * r + 6 * g + b + 16); + } + + return colors; +}; + +/** + * Apply rainbow to the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +NyanCat.prototype.rainbowify = function(str){ + var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; + this.colorIndex += 1; + return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; +}; + +/** + * Stdout helper. + */ + +function write(string) { + process.stdout.write(string); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +NyanCat.prototype = new F; +NyanCat.prototype.constructor = NyanCat; + + +}); // module: reporters/nyan.js + +require.register("reporters/progress.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Progress`. + */ + +exports = module.exports = Progress; + +/** + * General progress bar color. + */ + +Base.colors.progress = 90; + +/** + * Initialize a new `Progress` bar test reporter. + * + * @param {Runner} runner + * @param {Object} options + * @api public + */ + +function Progress(runner, options) { + Base.call(this, runner); + + var self = this + , options = options || {} + , stats = this.stats + , width = Base.window.width * .50 | 0 + , total = runner.total + , complete = 0 + , max = Math.max; + + // default chars + options.open = options.open || '['; + options.complete = options.complete || '▬'; + options.incomplete = options.incomplete || Base.symbols.dot; + options.close = options.close || ']'; + options.verbose = false; + + // tests started + runner.on('start', function(){ + console.log(); + cursor.hide(); + }); + + // tests complete + runner.on('test end', function(){ + complete++; + var incomplete = total - complete + , percent = complete / total + , n = width * percent | 0 + , i = width - n; + + cursor.CR(); + process.stdout.write('\u001b[J'); + process.stdout.write(color('progress', ' ' + options.open)); + process.stdout.write(Array(n).join(options.complete)); + process.stdout.write(Array(i).join(options.incomplete)); + process.stdout.write(color('progress', options.close)); + if (options.verbose) { + process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); + } + }); + + // tests are complete, output some stats + // and the failures if any + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +Progress.prototype = new F; +Progress.prototype.constructor = Progress; + + +}); // module: reporters/progress.js + +require.register("reporters/spec.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Spec`. + */ + +exports = module.exports = Spec; + +/** + * Initialize a new `Spec` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Spec(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , indents = 0 + , n = 0; + + function indent() { + return Array(indents).join(' ') + } + + runner.on('start', function(){ + console.log(); + }); + + runner.on('suite', function(suite){ + ++indents; + console.log(color('suite', '%s%s'), indent(), suite.title); + }); + + runner.on('suite end', function(suite){ + --indents; + if (1 == indents) console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = indent() + color('pending', ' - %s'); + console.log(fmt, test.title); + }); + + runner.on('pass', function(test){ + if ('fast' == test.speed) { + var fmt = indent() + + color('checkmark', ' ' + Base.symbols.ok) + + color('pass', ' %s '); + cursor.CR(); + console.log(fmt, test.title); + } else { + var fmt = indent() + + color('checkmark', ' ' + Base.symbols.ok) + + color('pass', ' %s ') + + color(test.speed, '(%dms)'); + cursor.CR(); + console.log(fmt, test.title, test.duration); + } + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +Spec.prototype = new F; +Spec.prototype.constructor = Spec; + + +}); // module: reporters/spec.js + +require.register("reporters/tap.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `TAP`. + */ + +exports = module.exports = TAP; + +/** + * Initialize a new `TAP` reporter. + * + * @param {Runner} runner + * @api public + */ + +function TAP(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , n = 1 + , passes = 0 + , failures = 0; + + runner.on('start', function(){ + var total = runner.grepTotal(runner.suite); + console.log('%d..%d', 1, total); + }); + + runner.on('test end', function(){ + ++n; + }); + + runner.on('pending', function(test){ + console.log('ok %d %s # SKIP -', n, title(test)); + }); + + runner.on('pass', function(test){ + passes++; + console.log('ok %d %s', n, title(test)); + }); + + runner.on('fail', function(test, err){ + failures++; + console.log('not ok %d %s', n, title(test)); + if (err.stack) console.log(err.stack.replace(/^/gm, ' ')); + }); + + runner.on('end', function(){ + console.log('# tests ' + (passes + failures)); + console.log('# pass ' + passes); + console.log('# fail ' + failures); + }); +} + +/** + * Return a TAP-safe title of `test` + * + * @param {Object} test + * @return {String} + * @api private + */ + +function title(test) { + return test.fullTitle().replace(/#/g, ''); +} + +}); // module: reporters/tap.js + +require.register("reporters/teamcity.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Teamcity`. + */ + +exports = module.exports = Teamcity; + +/** + * Initialize a new `Teamcity` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Teamcity(runner) { + Base.call(this, runner); + var stats = this.stats; + + runner.on('start', function() { + console.log("##teamcity[testSuiteStarted name='mocha.suite']"); + }); + + runner.on('test', function(test) { + console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); + }); + + runner.on('fail', function(test, err) { + console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); + }); + + runner.on('pending', function(test) { + console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); + }); + + runner.on('test end', function(test) { + console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); + }); + + runner.on('end', function() { + console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); + }); +} + +/** + * Escape the given `str`. + */ + +function escape(str) { + return str + .replace(/\|/g, "||") + .replace(/\n/g, "|n") + .replace(/\r/g, "|r") + .replace(/\[/g, "|[") + .replace(/\]/g, "|]") + .replace(/\u0085/g, "|x") + .replace(/\u2028/g, "|l") + .replace(/\u2029/g, "|p") + .replace(/'/g, "|'"); +} + +}); // module: reporters/teamcity.js + +require.register("reporters/xunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `XUnit`. + */ + +exports = module.exports = XUnit; + +/** + * Initialize a new `XUnit` reporter. + * + * @param {Runner} runner + * @api public + */ + +function XUnit(runner) { + Base.call(this, runner); + var stats = this.stats + , tests = [] + , self = this; + + runner.on('pass', function(test){ + tests.push(test); + }); + + runner.on('fail', function(test){ + tests.push(test); + }); + + runner.on('end', function(){ + console.log(tag('testsuite', { + name: 'Mocha Tests' + , tests: stats.tests + , failures: stats.failures + , errors: stats.failures + , skip: stats.tests - stats.failures - stats.passes + , timestamp: (new Date).toUTCString() + , time: stats.duration / 1000 + }, false)); + + tests.forEach(test); + console.log(''); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +function F(){}; +F.prototype = Base.prototype; +XUnit.prototype = new F; +XUnit.prototype.constructor = XUnit; + + +/** + * Output tag for the given `test.` + */ + +function test(test) { + var attrs = { + classname: test.parent.fullTitle() + , name: test.title + , time: test.duration / 1000 + }; + + if ('failed' == test.state) { + var err = test.err; + attrs.message = escape(err.message); + console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); + } else if (test.pending) { + console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); + } else { + console.log(tag('testcase', attrs, true) ); + } +} + +/** + * HTML tag helper. + */ + +function tag(name, attrs, close, content) { + var end = close ? '/>' : '>' + , pairs = [] + , tag; + + for (var key in attrs) { + pairs.push(key + '="' + escape(attrs[key]) + '"'); + } + + tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; + if (content) tag += content + ''; +} + +}); // module: reporters/xunit.js + +require.register("runnable.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runnable') + , milliseconds = require('./ms'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Object#toString(). + */ + +var toString = Object.prototype.toString; + +/** + * Expose `Runnable`. + */ + +module.exports = Runnable; + +/** + * Initialize a new `Runnable` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Runnable(title, fn) { + this.title = title; + this.fn = fn; + this.async = fn && fn.length; + this.sync = ! this.async; + this._timeout = 2000; + this._slow = 75; + this.timedOut = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +function F(){}; +F.prototype = EventEmitter.prototype; +Runnable.prototype = new F; +Runnable.prototype.constructor = Runnable; + + +/** + * Set & get timeout `ms`. + * + * @param {Number|String} ms + * @return {Runnable|Number} ms or self + * @api private + */ + +Runnable.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + if ('string' == typeof ms) ms = milliseconds(ms); + debug('timeout %d', ms); + this._timeout = ms; + if (this.timer) this.resetTimeout(); + return this; +}; + +/** + * Set & get slow `ms`. + * + * @param {Number|String} ms + * @return {Runnable|Number} ms or self + * @api private + */ + +Runnable.prototype.slow = function(ms){ + if (0 === arguments.length) return this._slow; + if ('string' == typeof ms) ms = milliseconds(ms); + debug('timeout %d', ms); + this._slow = ms; + return this; +}; + +/** + * Return the full title generated by recursively + * concatenating the parent's full title. + * + * @return {String} + * @api public + */ + +Runnable.prototype.fullTitle = function(){ + return this.parent.fullTitle() + ' ' + this.title; +}; + +/** + * Clear the timeout. + * + * @api private + */ + +Runnable.prototype.clearTimeout = function(){ + clearTimeout(this.timer); +}; + +/** + * Inspect the runnable void of private properties. + * + * @return {String} + * @api private + */ + +Runnable.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_' == key[0]) return; + if ('parent' == key) return '#'; + if ('ctx' == key) return '#'; + return val; + }, 2); +}; + +/** + * Reset the timeout. + * + * @api private + */ + +Runnable.prototype.resetTimeout = function(){ + var self = this + , ms = this.timeout(); + + this.clearTimeout(); + if (ms) { + this.timer = setTimeout(function(){ + self.callback(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } +}; + +/** + * Run the test and invoke `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runnable.prototype.run = function(fn){ + var self = this + , ms = this.timeout() + , start = new Date + , ctx = this.ctx + , finished + , emitted; + + if (ctx) ctx.runnable(this); + + // timeout + if (this.async) { + if (ms) { + this.timer = setTimeout(function(){ + done(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } + } + + // called multiple times + function multiple(err) { + if (emitted) return; + emitted = true; + self.emit('error', err || new Error('done() called multiple times')); + } + + // finished + function done(err) { + if (self.timedOut) return; + if (finished) return multiple(err); + self.clearTimeout(); + self.duration = new Date - start; + finished = true; + fn(err); + } + + // for .resetTimeout() + this.callback = done; + + // async + if (this.async) { + try { + this.fn.call(ctx, function(err){ + if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); + if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); + done(); + }); + } catch (err) { + done(err); + } + return; + } + + if (this.asyncOnly) { + return done(new Error('--async-only option in use without declaring `done()`')); + } + + // sync + try { + if (!this.pending) this.fn.call(ctx); + this.duration = new Date - start; + fn(); + } catch (err) { + fn(err); + } +}; + +}); // module: runnable.js + +require.register("runner.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runner') + , Test = require('./test') + , utils = require('./utils') + , filter = utils.filter + , keys = utils.keys + , noop = function(){}; + +/** + * Non-enumerable globals. + */ + +var globals = [ + 'setTimeout', + 'clearTimeout', + 'setInterval', + 'clearInterval', + 'XMLHttpRequest', + 'Date' +]; + +/** + * Expose `Runner`. + */ + +module.exports = Runner; + +/** + * Initialize a `Runner` for the given `suite`. + * + * Events: + * + * - `start` execution started + * - `end` execution complete + * - `suite` (suite) test suite execution started + * - `suite end` (suite) all tests (and sub-suites) have finished + * - `test` (test) test execution started + * - `test end` (test) test completed + * - `hook` (hook) hook execution started + * - `hook end` (hook) hook complete + * - `pass` (test) test passed + * - `fail` (test, err) test failed + * + * @api public + */ + +function Runner(suite) { + var self = this; + this._globals = []; + this.suite = suite; + this.total = suite.total(); + this.failures = 0; + this.on('test end', function(test){ self.checkGlobals(test); }); + this.on('hook end', function(hook){ self.checkGlobals(hook); }); + this.grep(/.*/); + this.globals(this.globalProps().concat(['errno'])); +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +function F(){}; +F.prototype = EventEmitter.prototype; +Runner.prototype = new F; +Runner.prototype.constructor = Runner; + + +/** + * Run tests with full titles matching `re`. Updates runner.total + * with number of tests matched. + * + * @param {RegExp} re + * @param {Boolean} invert + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.grep = function(re, invert){ + debug('grep %s', re); + this._grep = re; + this._invert = invert; + this.total = this.grepTotal(this.suite); + return this; +}; + +/** + * Returns the number of tests matching the grep search for the + * given suite. + * + * @param {Suite} suite + * @return {Number} + * @api public + */ + +Runner.prototype.grepTotal = function(suite) { + var self = this; + var total = 0; + + suite.eachTest(function(test){ + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (match) total++; + }); + + return total; +}; + +/** + * Return a list of global properties. + * + * @return {Array} + * @api private + */ + +Runner.prototype.globalProps = function() { + var props = utils.keys(global); + + // non-enumerables + for (var i = 0; i < globals.length; ++i) { + if (~utils.indexOf(props, globals[i])) continue; + props.push(globals[i]); + } + + return props; +}; + +/** + * Allow the given `arr` of globals. + * + * @param {Array} arr + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.globals = function(arr){ + if (0 == arguments.length) return this._globals; + debug('globals %j', arr); + utils.forEach(arr, function(arr){ + this._globals.push(arr); + }, this); + return this; +}; + +/** + * Check for global variable leaks. + * + * @api private + */ + +Runner.prototype.checkGlobals = function(test){ + if (this.ignoreLeaks) return; + var ok = this._globals; + var globals = this.globalProps(); + var isNode = process.kill; + var leaks; + + // check length - 2 ('errno' and 'location' globals) + if (isNode && 1 == ok.length - globals.length) return + else if (2 == ok.length - globals.length) return; + + leaks = filterLeaks(ok, globals); + this._globals = this._globals.concat(leaks); + + if (leaks.length > 1) { + this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); + } else if (leaks.length) { + this.fail(test, new Error('global leak detected: ' + leaks[0])); + } +}; + +/** + * Fail the given `test`. + * + * @param {Test} test + * @param {Error} err + * @api private + */ + +Runner.prototype.fail = function(test, err){ + ++this.failures; + test.state = 'failed'; + + if ('string' == typeof err) { + err = new Error('the string "' + err + '" was thrown, throw an Error :)'); + } + + this.emit('fail', test, err); +}; + +/** + * Fail the given `hook` with `err`. + * + * Hook failures (currently) hard-end due + * to that fact that a failing hook will + * surely cause subsequent tests to fail, + * causing jumbled reporting. + * + * @param {Hook} hook + * @param {Error} err + * @api private + */ + +Runner.prototype.failHook = function(hook, err){ + this.fail(hook, err); + this.emit('end'); +}; + +/** + * Run hook `name` callbacks and then invoke `fn()`. + * + * @param {String} name + * @param {Function} function + * @api private + */ + +Runner.prototype.hook = function(name, fn){ + var suite = this.suite + , hooks = suite['_' + name] + , self = this + , timer; + + function next(i) { + var hook = hooks[i]; + if (!hook) return fn(); + self.currentRunnable = hook; + + self.emit('hook', hook); + + hook.on('error', function(err){ + self.failHook(hook, err); + }); + + hook.run(function(err){ + hook.removeAllListeners('error'); + var testError = hook.error(); + if (testError) self.fail(self.test, testError); + if (err) return self.failHook(hook, err); + self.emit('hook end', hook); + next(++i); + }); + } + + process.nextTick(function(){ + next(0); + }); +}; + +/** + * Run hook `name` for the given array of `suites` + * in order, and callback `fn(err)`. + * + * @param {String} name + * @param {Array} suites + * @param {Function} fn + * @api private + */ + +Runner.prototype.hooks = function(name, suites, fn){ + var self = this + , orig = this.suite; + + function next(suite) { + self.suite = suite; + + if (!suite) { + self.suite = orig; + return fn(); + } + + self.hook(name, function(err){ + if (err) { + self.suite = orig; + return fn(err); + } + + next(suites.pop()); + }); + } + + next(suites.pop()); +}; + +/** + * Run hooks from the top level down. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookUp = function(name, fn){ + var suites = [this.suite].concat(this.parents()).reverse(); + this.hooks(name, suites, fn); +}; + +/** + * Run hooks from the bottom up. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookDown = function(name, fn){ + var suites = [this.suite].concat(this.parents()); + this.hooks(name, suites, fn); +}; + +/** + * Return an array of parent Suites from + * closest to furthest. + * + * @return {Array} + * @api private + */ + +Runner.prototype.parents = function(){ + var suite = this.suite + , suites = []; + while (suite = suite.parent) suites.push(suite); + return suites; +}; + +/** + * Run the current test and callback `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTest = function(fn){ + var test = this.test + , self = this; + + if (this.asyncOnly) test.asyncOnly = true; + + try { + test.on('error', function(err){ + self.fail(test, err); + }); + test.run(fn); + } catch (err) { + fn(err); + } +}; + +/** + * Run tests in the given `suite` and invoke + * the callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTests = function(suite, fn){ + var self = this + , tests = suite.tests.slice() + , test; + + function next(err) { + // if we bail after first err + if (self.failures && suite._bail) return fn(); + + // next test + test = tests.shift(); + + // all done + if (!test) return fn(); + + // grep + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (!match) return next(); + + // pending + if (test.pending) { + self.emit('pending', test); + self.emit('test end', test); + return next(); + } + + // execute test and hook(s) + self.emit('test', self.test = test); + self.hookDown('beforeEach', function(){ + self.currentRunnable = self.test; + self.runTest(function(err){ + test = self.test; + + if (err) { + self.fail(test, err); + self.emit('test end', test); + return self.hookUp('afterEach', next); + } + + test.state = 'passed'; + self.emit('pass', test); + self.emit('test end', test); + self.hookUp('afterEach', next); + }); + }); + } + + this.next = next; + next(); +}; + +/** + * Run the given `suite` and invoke the + * callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runSuite = function(suite, fn){ + var total = this.grepTotal(suite) + , self = this + , i = 0; + + debug('run suite %s', suite.fullTitle()); + + if (!total) return fn(); + + this.emit('suite', this.suite = suite); + + function next() { + var curr = suite.suites[i++]; + if (!curr) return done(); + self.runSuite(curr, next); + } + + function done() { + self.suite = suite; + self.hook('afterAll', function(){ + self.emit('suite end', suite); + fn(); + }); + } + + this.hook('beforeAll', function(){ + self.runTests(suite, next); + }); +}; + +/** + * Handle uncaught exceptions. + * + * @param {Error} err + * @api private + */ + +Runner.prototype.uncaught = function(err){ + debug('uncaught exception %s', err.message); + var runnable = this.currentRunnable; + if (!runnable || 'failed' == runnable.state) return; + runnable.clearTimeout(); + err.uncaught = true; + this.fail(runnable, err); + + // recover from test + if ('test' == runnable.type) { + this.emit('test end', runnable); + this.hookUp('afterEach', this.next); + return; + } + + // bail on hooks + this.emit('end'); +}; + +/** + * Run the root suite and invoke `fn(failures)` + * on completion. + * + * @param {Function} fn + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.run = function(fn){ + var self = this + , fn = fn || function(){}; + + debug('start'); + + // callback + this.on('end', function(){ + debug('end'); + process.removeListener('uncaughtException', function(err){ + self.uncaught(err); + }); + fn(self.failures); + }); + + // run suites + this.emit('start'); + this.runSuite(this.suite, function(){ + debug('finished running'); + self.emit('end'); + }); + + // uncaught exception + process.on('uncaughtException', function(err){ + self.uncaught(err); + }); + + return this; +}; + +/** + * Filter leaks with the given globals flagged as `ok`. + * + * @param {Array} ok + * @param {Array} globals + * @return {Array} + * @api private + */ + +function filterLeaks(ok, globals) { + return filter(globals, function(key){ + var matched = filter(ok, function(ok){ + if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); + // Opera and IE expose global variables for HTML element IDs (issue #243) + if (/^mocha-/.test(key)) return true; + return key == ok; + }); + return matched.length == 0 && (!global.navigator || 'onerror' !== key); + }); +} + +}); // module: runner.js + +require.register("suite.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:suite') + , milliseconds = require('./ms') + , utils = require('./utils') + , Hook = require('./hook'); + +/** + * Expose `Suite`. + */ + +exports = module.exports = Suite; + +/** + * Create a new `Suite` with the given `title` + * and parent `Suite`. When a suite with the + * same title is already present, that suite + * is returned to provide nicer reporter + * and more flexible meta-testing. + * + * @param {Suite} parent + * @param {String} title + * @return {Suite} + * @api public + */ + +exports.create = function(parent, title){ + var suite = new Suite(title, parent.ctx); + suite.parent = parent; + if (parent.pending) suite.pending = true; + title = suite.fullTitle(); + parent.addSuite(suite); + return suite; +}; + +/** + * Initialize a new `Suite` with the given + * `title` and `ctx`. + * + * @param {String} title + * @param {Context} ctx + * @api private + */ + +function Suite(title, ctx) { + this.title = title; + this.ctx = ctx; + this.suites = []; + this.tests = []; + this.pending = false; + this._beforeEach = []; + this._beforeAll = []; + this._afterEach = []; + this._afterAll = []; + this.root = !title; + this._timeout = 2000; + this._slow = 75; + this._bail = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +function F(){}; +F.prototype = EventEmitter.prototype; +Suite.prototype = new F; +Suite.prototype.constructor = Suite; + + +/** + * Return a clone of this `Suite`. + * + * @return {Suite} + * @api private + */ + +Suite.prototype.clone = function(){ + var suite = new Suite(this.title); + debug('clone'); + suite.ctx = this.ctx; + suite.timeout(this.timeout()); + suite.slow(this.slow()); + suite.bail(this.bail()); + return suite; +}; + +/** + * Set timeout `ms` or short-hand such as "2s". + * + * @param {Number|String} ms + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + if ('string' == typeof ms) ms = milliseconds(ms); + debug('timeout %d', ms); + this._timeout = parseInt(ms, 10); + return this; +}; + +/** + * Set slow `ms` or short-hand such as "2s". + * + * @param {Number|String} ms + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.slow = function(ms){ + if (0 === arguments.length) return this._slow; + if ('string' == typeof ms) ms = milliseconds(ms); + debug('slow %d', ms); + this._slow = ms; + return this; +}; + +/** + * Sets whether to bail after first error. + * + * @parma {Boolean} bail + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.bail = function(bail){ + if (0 == arguments.length) return this._bail; + debug('bail %s', bail); + this._bail = bail; + return this; +}; + +/** + * Run `fn(test[, done])` before running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.beforeAll = function(fn){ + if (this.pending) return this; + var hook = new Hook('"before all" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._beforeAll.push(hook); + this.emit('beforeAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.afterAll = function(fn){ + if (this.pending) return this; + var hook = new Hook('"after all" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._afterAll.push(hook); + this.emit('afterAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` before each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.beforeEach = function(fn){ + if (this.pending) return this; + var hook = new Hook('"before each" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._beforeEach.push(hook); + this.emit('beforeEach', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.afterEach = function(fn){ + if (this.pending) return this; + var hook = new Hook('"after each" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._afterEach.push(hook); + this.emit('afterEach', hook); + return this; +}; + +/** + * Add a test `suite`. + * + * @param {Suite} suite + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addSuite = function(suite){ + suite.parent = this; + suite.timeout(this.timeout()); + suite.slow(this.slow()); + suite.bail(this.bail()); + this.suites.push(suite); + this.emit('suite', suite); + return this; +}; + +/** + * Add a `test` to this suite. + * + * @param {Test} test + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addTest = function(test){ + test.parent = this; + test.timeout(this.timeout()); + test.slow(this.slow()); + test.ctx = this.ctx; + this.tests.push(test); + this.emit('test', test); + return this; +}; + +/** + * Return the full title generated by recursively + * concatenating the parent's full title. + * + * @return {String} + * @api public + */ + +Suite.prototype.fullTitle = function(){ + if (this.parent) { + var full = this.parent.fullTitle(); + if (full) return full + ' ' + this.title; + } + return this.title; +}; + +/** + * Return the total number of tests. + * + * @return {Number} + * @api public + */ + +Suite.prototype.total = function(){ + return utils.reduce(this.suites, function(sum, suite){ + return sum + suite.total(); + }, 0) + this.tests.length; +}; + +/** + * Iterates through each suite recursively to find + * all tests. Applies a function in the format + * `fn(test)`. + * + * @param {Function} fn + * @return {Suite} + * @api private + */ + +Suite.prototype.eachTest = function(fn){ + utils.forEach(this.tests, fn); + utils.forEach(this.suites, function(suite){ + suite.eachTest(fn); + }); + return this; +}; + +}); // module: suite.js + +require.register("test.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Test`. + */ + +module.exports = Test; + +/** + * Initialize a new `Test` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Test(title, fn) { + Runnable.call(this, title, fn); + this.pending = !fn; + this.type = 'test'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +function F(){}; +F.prototype = Runnable.prototype; +Test.prototype = new F; +Test.prototype.constructor = Test; + + +}); // module: test.js + +require.register("utils.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var fs = require('browser/fs') + , path = require('browser/path') + , join = path.join + , debug = require('browser/debug')('mocha:watch'); + +/** + * Ignored directories. + */ + +var ignore = ['node_modules', '.git']; + +/** + * Escape special characters in the given string of html. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +}; + +/** + * Array#forEach (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} scope + * @api private + */ + +exports.forEach = function(arr, fn, scope){ + for (var i = 0, l = arr.length; i < l; i++) + fn.call(scope, arr[i], i); +}; + +/** + * Array#indexOf (<=IE8) + * + * @parma {Array} arr + * @param {Object} obj to find index of + * @param {Number} start + * @api private + */ + +exports.indexOf = function(arr, obj, start){ + for (var i = start || 0, l = arr.length; i < l; i++) { + if (arr[i] === obj) + return i; + } + return -1; +}; + +/** + * Array#reduce (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} initial value + * @api private + */ + +exports.reduce = function(arr, fn, val){ + var rval = val; + + for (var i = 0, l = arr.length; i < l; i++) { + rval = fn(rval, arr[i], i, arr); + } + + return rval; +}; + +/** + * Array#filter (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @api private + */ + +exports.filter = function(arr, fn){ + var ret = []; + + for (var i = 0, l = arr.length; i < l; i++) { + var val = arr[i]; + if (fn(val, i, arr)) ret.push(val); + } + + return ret; +}; + +/** + * Object.keys (<=IE8) + * + * @param {Object} obj + * @return {Array} keys + * @api private + */ + +exports.keys = Object.keys || function(obj) { + var keys = [] + , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 + + for (var key in obj) { + if (has.call(obj, key)) { + keys.push(key); + } + } + + return keys; +}; + +/** + * Watch the given `files` for changes + * and invoke `fn(file)` on modification. + * + * @param {Array} files + * @param {Function} fn + * @api private + */ + +exports.watch = function(files, fn){ + var options = { interval: 100 }; + files.forEach(function(file){ + debug('file %s', file); + fs.watchFile(file, options, function(curr, prev){ + if (prev.mtime < curr.mtime) fn(file); + }); + }); +}; + +/** + * Ignored files. + */ + +function ignored(path){ + return !~ignore.indexOf(path); +} + +/** + * Lookup files in the given `dir`. + * + * @return {Array} + * @api private + */ + +exports.files = function(dir, ret){ + ret = ret || []; + + fs.readdirSync(dir) + .filter(ignored) + .forEach(function(path){ + path = join(dir, path); + if (fs.statSync(path).isDirectory()) { + exports.files(path, ret); + } else if (path.match(/\.(js|coffee)$/)) { + ret.push(path); + } + }); + + return ret; +}; + +/** + * Compute a slug from the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.slug = function(str){ + return str + .toLowerCase() + .replace(/ +/g, '-') + .replace(/[^-\w]/g, ''); +}; + +/** + * Strip the function definition from `str`, + * and re-indent for pre whitespace. + */ + +exports.clean = function(str) { + str = str + .replace(/^function *\(.*\) *{/, '') + .replace(/\s+\}$/, ''); + + var spaces = str.match(/^\n?( *)/)[1].length + , re = new RegExp('^ {' + spaces + '}', 'gm'); + + str = str.replace(re, ''); + + return exports.trim(str); +}; + +/** + * Escape regular expression characters in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.escapeRegexp = function(str){ + return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); +}; + +/** + * Trim the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.trim = function(str){ + return str.replace(/^\s+|\s+$/g, ''); +}; + +/** + * Parse the given `qs`. + * + * @param {String} qs + * @return {Object} + * @api private + */ + +exports.parseQuery = function(qs){ + return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ + var i = pair.indexOf('=') + , key = pair.slice(0, i) + , val = pair.slice(++i); + + obj[key] = decodeURIComponent(val); + return obj; + }, {}); +}; + +/** + * Highlight the given string of `js`. + * + * @param {String} js + * @return {String} + * @api private + */ + +function highlight(js) { + return js + .replace(//g, '>') + .replace(/\/\/(.*)/gm, '//$1') + .replace(/('.*?')/gm, '$1') + .replace(/(\d+\.\d+)/gm, '$1') + .replace(/(\d+)/gm, '$1') + .replace(/\bnew *(\w+)/gm, 'new $1') + .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') +} + +/** + * Highlight the contents of tag `name`. + * + * @param {String} name + * @api private + */ + +exports.highlightTags = function(name) { + var code = document.getElementsByTagName(name); + for (var i = 0, len = code.length; i < len; ++i) { + code[i].innerHTML = highlight(code[i].innerHTML); + } +}; + +}); // module: utils.js +/** + * Node shims. + * + * These are meant only to allow + * mocha.js to run untouched, not + * to allow running node code in + * the browser. + */ + +process = {}; +process.exit = function(status){}; +process.stdout = {}; +global = window; + +/** + * next tick implementation. + */ + +process.nextTick = (function(){ + // postMessage behaves badly on IE8 + if (window.ActiveXObject || !window.postMessage) { + return function(fn){ fn() }; + } + + // based on setZeroTimeout by David Baron + // - http://dbaron.org/log/20100309-faster-timeouts + var timeouts = [] + , name = 'mocha-zero-timeout' + + window.addEventListener('message', function(e){ + if (e.source == window && e.data == name) { + if (e.stopPropagation) e.stopPropagation(); + if (timeouts.length) timeouts.shift()(); + } + }, true); + + return function(fn){ + timeouts.push(fn); + window.postMessage(name, '*'); + } +})(); + +/** + * Remove uncaughtException listener. + */ + +process.removeListener = function(e){ + if ('uncaughtException' == e) { + window.onerror = null; + } +}; + +/** + * Implements uncaughtException listener. + */ + +process.on = function(e, fn){ + if ('uncaughtException' == e) { + window.onerror = function(err, url, line){ + fn(new Error(err + ' (' + url + ':' + line + ')')); + }; + } +}; + +// boot +;(function(){ + + /** + * Expose mocha. + */ + + var Mocha = window.Mocha = require('mocha'), + mocha = window.mocha = new Mocha({ reporter: 'html' }); + + /** + * Override ui to ensure that the ui functions are initialized. + * Normally this would happen in Mocha.prototype.loadFiles. + */ + + mocha.ui = function(ui){ + Mocha.prototype.ui.call(this, ui); + this.suite.emit('pre-require', window, null, this); + return this; + }; + + /** + * Setup mocha with the given setting options. + */ + + mocha.setup = function(opts){ + if ('string' == typeof opts) opts = { ui: opts }; + for (var opt in opts) this[opt](opts[opt]); + return this; + }; + + /** + * Run mocha, returning the Runner. + */ + + mocha.run = function(fn){ + var options = mocha.options; + mocha.globals('location'); + + var query = Mocha.utils.parseQuery(window.location.search || ''); + if (query.grep) mocha.grep(query.grep); + if (query.invert) mocha.invert(); + + return Mocha.prototype.run.call(mocha, function(){ + Mocha.utils.highlightTags('code'); + if (fn) fn(); + }); + }; +})(); +})(); \ No newline at end of file diff --git a/node_modules/component-type/test/tests.js b/node_modules/component-type/test/tests.js new file mode 100644 index 00000000..cbec75dc --- /dev/null +++ b/node_modules/component-type/test/tests.js @@ -0,0 +1,72 @@ +var type = require('type') + , assert = require('component-assert'); + +describe('type', function(){ + it('should match objects', function(){ + function Foo(){} + assert('object' === type({})); + assert('object' === type(new Foo)); + }); + + it('should match numbers', function(){ + assert('number' === type(12)); + assert('number' === type(1.0)); + assert('number' === type(-5)); + assert('number' === type(new Number(123))); + assert('number' === type(Infinity)); + }); + + it('should match NaN', function () { + assert('nan' === type(NaN)); + }); + + it('should match strings', function(){ + assert('string' === type("test")); + assert('string' === type(new String('whoop'))); + }); + + it('should match dates', function(){ + assert('date' === type(new Date)); + }); + + it('should match booleans', function(){ + assert('boolean' === type(true)); + assert('boolean' === type(false)); + assert('boolean' === type(new Boolean(true))); + }); + + it('should match null', function(){ + assert('null' === type(null)); + }); + + it('should match undefined', function(){ + assert('undefined' === type()); + assert('undefined' === type(undefined)); + }); + + it('should match arrays', function(){ + assert('array' === type([])); + assert('array' === type(new Array())); + }); + + it('should match regexps', function(){ + assert('regexp' === type(/asdf/)); + assert('regexp' === type(new RegExp('weee'))); + }); + + it('should match functions', function(){ + assert('function' === type(function(){})); + }); + + it('should match arguments', function(){ + assert('arguments' === type(arguments)); + }); + + it('should match elements', function(){ + assert('element' === type(document.createElement('div'))); + }); + + it('should match errors', function(){ + assert('error' === type(new Error('Ups!'))); + }); +}); diff --git a/node_modules/ease-component/.npmignore b/node_modules/ease-component/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/ease-component/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/ease-component/Makefile b/node_modules/ease-component/Makefile new file mode 100644 index 00000000..98a9de91 --- /dev/null +++ b/node_modules/ease-component/Makefile @@ -0,0 +1,14 @@ + +build: components index.js + @component build --dev + +components: + @component install --dev + +clean: + rm -fr build components template.js + +list: + @cat index.js | grep exports | sed 's/exports.//' | cut -f 1 -d ' ' + +.PHONY: clean list diff --git a/node_modules/ease-component/Readme.md b/node_modules/ease-component/Readme.md new file mode 100644 index 00000000..1d98bc11 --- /dev/null +++ b/node_modules/ease-component/Readme.md @@ -0,0 +1,106 @@ + +# ease + + Easing functions (for canvas etc) + + - linear + - inQuad + - outQuad + - inOutQuad + - inCube + - outCube + - inOutCube + - inQuart + - outQuart + - inOutQuart + - inQuint + - outQuint + - inOutQuint + - inSine + - outSine + - inOutSine + - inExpo + - outExpo + - inOutExpo + - inCirc + - outCirc + - inOutCirc + - inBack + - outBack + - inOutBack + - inBounce + - outBounce + - inOutBounce + +## Aliases + + - in-quad + - out-quad + - in-out-quad + - in-cube + - out-cube + - in-out-cube + - in-quart + - out-quart + - in-out-quart + - in-quint + - out-quint + - in-out-quint + - in-sine + - out-sine + - in-out-sine + - in-expo + - out-expo + - in-out-expo + - in-circ + - out-circ + - in-out-circ + - in-back + - out-back + - in-out-back + - in-bounce + - out-bounce + - in-out-bounce + +## Example + +```js +var ease = require('ease'); +var requestAnimationFrame = require('raf'); +var canvas = document.querySelector('canvas'); +var ctx = canvas.getContext('2d'); + +var stop = false; +function animate() { + if (stop) return; + requestAnimationFrame(animate); + draw(); +} + +var startx = 20; +var x = startx; +var destx = 300; +var y = 400 / 2; +var duration = 1000; +var start = Date.now(); +var end = start + duration; + +function draw() { + var now = Date.now(); + if (now - start >= duration) stop = true; + var p = (now - start) / duration; + val = ease.inOutBounce(p); + x = startx + (destx - startx) * val; + canvas.width = canvas.width; + ctx.fillStyle = 'red'; + ctx.arc(x, y, 10, 0, Math.PI * 2, false); + ctx.fill(); +} + +animate(); + +``` + +# License + + MIT diff --git a/node_modules/ease-component/component.json b/node_modules/ease-component/component.json new file mode 100644 index 00000000..6aae35d0 --- /dev/null +++ b/node_modules/ease-component/component.json @@ -0,0 +1,15 @@ +{ + "name": "ease", + "repo": "component/ease", + "description": "Easing functions (for canvas etc)", + "version": "1.0.0", + "keywords": ["ease", "easing", "tween"], + "dependencies": {}, + "development": { + "component/raf": "*" + }, + "scripts": [ + "index.js" + ], + "license": "MIT" +} \ No newline at end of file diff --git a/node_modules/ease-component/example.html b/node_modules/ease-component/example.html new file mode 100644 index 00000000..bfff6476 --- /dev/null +++ b/node_modules/ease-component/example.html @@ -0,0 +1,46 @@ + + + + + + + + \ No newline at end of file diff --git a/node_modules/ease-component/index.js b/node_modules/ease-component/index.js new file mode 100644 index 00000000..4516199b --- /dev/null +++ b/node_modules/ease-component/index.js @@ -0,0 +1,170 @@ + +// easing functions from "Tween.js" + +exports.linear = function(n){ + return n; +}; + +exports.inQuad = function(n){ + return n * n; +}; + +exports.outQuad = function(n){ + return n * (2 - n); +}; + +exports.inOutQuad = function(n){ + n *= 2; + if (n < 1) return 0.5 * n * n; + return - 0.5 * (--n * (n - 2) - 1); +}; + +exports.inCube = function(n){ + return n * n * n; +}; + +exports.outCube = function(n){ + return --n * n * n + 1; +}; + +exports.inOutCube = function(n){ + n *= 2; + if (n < 1) return 0.5 * n * n * n; + return 0.5 * ((n -= 2 ) * n * n + 2); +}; + +exports.inQuart = function(n){ + return n * n * n * n; +}; + +exports.outQuart = function(n){ + return 1 - (--n * n * n * n); +}; + +exports.inOutQuart = function(n){ + n *= 2; + if (n < 1) return 0.5 * n * n * n * n; + return -0.5 * ((n -= 2) * n * n * n - 2); +}; + +exports.inQuint = function(n){ + return n * n * n * n * n; +} + +exports.outQuint = function(n){ + return --n * n * n * n * n + 1; +} + +exports.inOutQuint = function(n){ + n *= 2; + if (n < 1) return 0.5 * n * n * n * n * n; + return 0.5 * ((n -= 2) * n * n * n * n + 2); +}; + +exports.inSine = function(n){ + return 1 - Math.cos(n * Math.PI / 2 ); +}; + +exports.outSine = function(n){ + return Math.sin(n * Math.PI / 2); +}; + +exports.inOutSine = function(n){ + return .5 * (1 - Math.cos(Math.PI * n)); +}; + +exports.inExpo = function(n){ + return 0 == n ? 0 : Math.pow(1024, n - 1); +}; + +exports.outExpo = function(n){ + return 1 == n ? n : 1 - Math.pow(2, -10 * n); +}; + +exports.inOutExpo = function(n){ + if (0 == n) return 0; + if (1 == n) return 1; + if ((n *= 2) < 1) return .5 * Math.pow(1024, n - 1); + return .5 * (-Math.pow(2, -10 * (n - 1)) + 2); +}; + +exports.inCirc = function(n){ + return 1 - Math.sqrt(1 - n * n); +}; + +exports.outCirc = function(n){ + return Math.sqrt(1 - (--n * n)); +}; + +exports.inOutCirc = function(n){ + n *= 2 + if (n < 1) return -0.5 * (Math.sqrt(1 - n * n) - 1); + return 0.5 * (Math.sqrt(1 - (n -= 2) * n) + 1); +}; + +exports.inBack = function(n){ + var s = 1.70158; + return n * n * (( s + 1 ) * n - s); +}; + +exports.outBack = function(n){ + var s = 1.70158; + return --n * n * ((s + 1) * n + s) + 1; +}; + +exports.inOutBack = function(n){ + var s = 1.70158 * 1.525; + if ( ( n *= 2 ) < 1 ) return 0.5 * ( n * n * ( ( s + 1 ) * n - s ) ); + return 0.5 * ( ( n -= 2 ) * n * ( ( s + 1 ) * n + s ) + 2 ); +}; + +exports.inBounce = function(n){ + return 1 - exports.outBounce(1 - n); +}; + +exports.outBounce = function(n){ + if ( n < ( 1 / 2.75 ) ) { + return 7.5625 * n * n; + } else if ( n < ( 2 / 2.75 ) ) { + return 7.5625 * ( n -= ( 1.5 / 2.75 ) ) * n + 0.75; + } else if ( n < ( 2.5 / 2.75 ) ) { + return 7.5625 * ( n -= ( 2.25 / 2.75 ) ) * n + 0.9375; + } else { + return 7.5625 * ( n -= ( 2.625 / 2.75 ) ) * n + 0.984375; + } +}; + +exports.inOutBounce = function(n){ + if (n < .5) return exports.inBounce(n * 2) * .5; + return exports.outBounce(n * 2 - 1) * .5 + .5; +}; + +// aliases + +exports['in-quad'] = exports.inQuad; +exports['out-quad'] = exports.outQuad; +exports['in-out-quad'] = exports.inOutQuad; +exports['in-cube'] = exports.inCube; +exports['out-cube'] = exports.outCube; +exports['in-out-cube'] = exports.inOutCube; +exports['in-quart'] = exports.inQuart; +exports['out-quart'] = exports.outQuart; +exports['in-out-quart'] = exports.inOutQuart; +exports['in-quint'] = exports.inQuint; +exports['out-quint'] = exports.outQuint; +exports['in-out-quint'] = exports.inOutQuint; +exports['in-sine'] = exports.inSine; +exports['out-sine'] = exports.outSine; +exports['in-out-sine'] = exports.inOutSine; +exports['in-expo'] = exports.inExpo; +exports['out-expo'] = exports.outExpo; +exports['in-out-expo'] = exports.inOutExpo; +exports['in-circ'] = exports.inCirc; +exports['out-circ'] = exports.outCirc; +exports['in-out-circ'] = exports.inOutCirc; +exports['in-back'] = exports.inBack; +exports['out-back'] = exports.outBack; +exports['in-out-back'] = exports.inOutBack; +exports['in-bounce'] = exports.inBounce; +exports['out-bounce'] = exports.outBounce; +exports['in-out-bounce'] = exports.inOutBounce; diff --git a/node_modules/ease-component/package.json b/node_modules/ease-component/package.json new file mode 100644 index 00000000..c4a82543 --- /dev/null +++ b/node_modules/ease-component/package.json @@ -0,0 +1,13 @@ +{ + "name": "ease-component", + "description": "Easing functions (for canvas etc)", + "version": "1.0.0", + "keywords": ["ease", "easing", "tween"], + "dependencies": {}, + "component": { + "scripts": { + "ease/index.js": "index.js" + } + }, + "license": "MIT" +} diff --git a/node_modules/global-object/README.md b/node_modules/global-object/README.md new file mode 100644 index 00000000..188a6b1e --- /dev/null +++ b/node_modules/global-object/README.md @@ -0,0 +1,68 @@ +# global-object + +There are at least 3 different ways to reference the global object mentioned in ES6/2015 + + * `window` historically on HTML pages + * `self` in Workers, and historically on HTML pages too + * `global` in basically all server side implementation of JavaScript + +If we search in Github, the summed amount of `typeof window` or `typeof global` checks, +mostly to understand which one is available, is about 23 millions of times. + +This is madness, and since there's no reason at all to prefer anything different from `global` +for an object defined indeed as the global object in the global scope, I've decided to create +this page in order to put an end to all this. + +- - - - + +Forget about `window` and `self` in Workers, normalize your work-flow once for all +and with or without browserify in place! + + +### As first script in your page +This is the most straight forward way to have it defined everywhere as such +```html + +``` +No need to disturb the network, no need to ever update the script even if a browser +will eventually expose `global` reference. It goes there to stay. + + +### As first script in your Worker +Same goes with Web Workers and others, the code is exactly the same, without the node: +```html +var global=global||this; +``` +Forget about `self` or `typeof window` checks, we've got `global`! + + +### As anything else +ES6, node itself, whatever ... +```js +// ES6 +import global from 'global-object'; + +// npm require +var global = require('global-object'); + +// browser +script.src = 'global-object.js'; +``` +Just use [global-object](global-object.js) + + +### Strict compatible! +Yes, the `this` reference in the global scope is always the global object. +In HTML pages like in workers, it will work everywhere even after `"use strict"` directive! + + +### Content Security Policy Compatible +Using this meta will solve all problems: +```html + +``` +Great, no network request required, and `global` available under CSP too! + + +### License +Nope, nothing ... do what you want, literally! \ No newline at end of file diff --git a/node_modules/global-object/global-object.js b/node_modules/global-object/global-object.js new file mode 100644 index 00000000..8f88a9d6 --- /dev/null +++ b/node_modules/global-object/global-object.js @@ -0,0 +1 @@ +(function($){try{$('export default global')}catch(e){try{$('export default self')}catch(e){try{module.exports=global}catch(e){try{self.global=self}catch(e){window.global=window}}}}}(eval)) \ No newline at end of file diff --git a/node_modules/global-object/package.json b/node_modules/global-object/package.json new file mode 100644 index 00000000..766da53a --- /dev/null +++ b/node_modules/global-object/package.json @@ -0,0 +1,22 @@ +{ + "name": "global-object", + "version": "1.0.0", + "description": "just the global object", + "main": "global-object.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/WebReflection/global-object.git" + }, + "keywords": [ + "global" + ], + "author": "Andrea Giammarchi", + "license": "WTFPL", + "bugs": { + "url": "https://github.com/WebReflection/global-object/issues" + }, + "homepage": "https://github.com/WebReflection/global-object" +} diff --git a/node_modules/has-translate3d/.npmignore b/node_modules/has-translate3d/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/has-translate3d/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/has-translate3d/History.md b/node_modules/has-translate3d/History.md new file mode 100644 index 00000000..1a635a25 --- /dev/null +++ b/node_modules/has-translate3d/History.md @@ -0,0 +1,16 @@ + +0.0.3 / 2014-05-20 +================== + + * index: don't use `return` at the top level + * index: fix for IE8 [yields] (fixes #3) + +0.0.2 / 2013-04-05 +================== + + * index: fix computed style lookeup + +0.0.1 / 2013-04-04 +================== + + * initial release diff --git a/node_modules/has-translate3d/Makefile b/node_modules/has-translate3d/Makefile new file mode 100644 index 00000000..0f14dac3 --- /dev/null +++ b/node_modules/has-translate3d/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components template.js + +.PHONY: clean diff --git a/node_modules/has-translate3d/Readme.md b/node_modules/has-translate3d/Readme.md new file mode 100644 index 00000000..20b228e5 --- /dev/null +++ b/node_modules/has-translate3d/Readme.md @@ -0,0 +1,17 @@ + +# has-translate3d + + Feature detection of css `translate3d` + +## Installation + + $ component install component/has-translate3d + +## API + + Exports `true` if the engine supports `translate3d`, + or `false` otherwise. + +## License + + MIT diff --git a/node_modules/has-translate3d/component.json b/node_modules/has-translate3d/component.json new file mode 100644 index 00000000..70ab8066 --- /dev/null +++ b/node_modules/has-translate3d/component.json @@ -0,0 +1,15 @@ +{ + "name": "has-translate3d", + "repo": "component/has-translate3d", + "description": "Feature detection of css translate3d", + "version": "0.0.3", + "keywords": [], + "dependencies": { + "component/transform-property": "0.0.1" + }, + "development": {}, + "license": "MIT", + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/has-translate3d/index.js b/node_modules/has-translate3d/index.js new file mode 100644 index 00000000..6bcd0b97 --- /dev/null +++ b/node_modules/has-translate3d/index.js @@ -0,0 +1,24 @@ + +var prop = require('transform-property'); + +// IE <=8 doesn't have `getComputedStyle` +if (!prop || !window.getComputedStyle) { + module.exports = false; + +} else { + var map = { + webkitTransform: '-webkit-transform', + OTransform: '-o-transform', + msTransform: '-ms-transform', + MozTransform: '-moz-transform', + transform: 'transform' + }; + + // from: https://gist.github.com/lorenzopolidori/3794226 + var el = document.createElement('div'); + el.style[prop] = 'translate3d(1px,1px,1px)'; + document.body.insertBefore(el, null); + var val = getComputedStyle(el).getPropertyValue(map[prop]); + document.body.removeChild(el); + module.exports = null != val && val.length && 'none' != val; +} diff --git a/node_modules/has-translate3d/package.json b/node_modules/has-translate3d/package.json new file mode 100644 index 00000000..1a44e244 --- /dev/null +++ b/node_modules/has-translate3d/package.json @@ -0,0 +1,15 @@ +{ + "name": "has-translate3d", + "description": "Feature detection of css translate3d", + "version": "0.0.3", + "keywords": [], + "license": "MIT", + "dependencies": { + "transform-property": "0.0.1" + }, + "component": { + "scripts": { + "has-translate3d/index.js": "index.js" + } + } +} diff --git a/node_modules/prop-detect/.travis.yml b/node_modules/prop-detect/.travis.yml new file mode 100644 index 00000000..b452cbd6 --- /dev/null +++ b/node_modules/prop-detect/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - '0.12' +before_script: + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start diff --git a/node_modules/prop-detect/Makefile b/node_modules/prop-detect/Makefile new file mode 100644 index 00000000..532eaaa9 --- /dev/null +++ b/node_modules/prop-detect/Makefile @@ -0,0 +1,7 @@ +webpack: + @webpack-dev-server 'mocha!./test/test.js' --hot --inline + +test: + @karma start + +.PHONY: test diff --git a/node_modules/prop-detect/Readme.md b/node_modules/prop-detect/Readme.md new file mode 100644 index 00000000..aedec2a0 --- /dev/null +++ b/node_modules/prop-detect/Readme.md @@ -0,0 +1,29 @@ +# prop-detect + +[![Build Status](https://secure.travis-ci.org/chemzqm/prop-detect.svg)](http://travis-ci.org/chemzqm/prop-detect) + + Detect animation properties, it's annoying to install each of them. + :smiley: + +## Install + + npm i prop-detect -S + +## Usage + +``` js +var detect = require('prop-detect') +var transform = detect.transform +var transition = detect.transition +var touchAction = detect.touchAction +var transitionend = detect.transitionend +var has3d = detect.has3d // true or false +``` + +## API + +* `transform` style name +* `transition` style name +* `touchAction` style name +* `transitionend` event name +* `has3d` true of false diff --git a/node_modules/prop-detect/index.js b/node_modules/prop-detect/index.js new file mode 100644 index 00000000..d7b034cb --- /dev/null +++ b/node_modules/prop-detect/index.js @@ -0,0 +1,56 @@ +var transform = null +;(function () { + var styles = [ + 'webkitTransform', + 'MozTransform', + 'msTransform', + 'OTransform', + 'transform' + ]; + + var el = document.createElement('p'); + + for (var i = 0; i < styles.length; i++) { + if (null != el.style[styles[i]]) { + transform = styles[i]; + break; + } + } +})() + +/** + * Transition-end mapping + */ +var transitionEnd = null +;(function () { + var map = { + 'WebkitTransition' : 'webkitTransitionEnd', + 'MozTransition' : 'transitionend', + 'OTransition' : 'oTransitionEnd', + 'msTransition' : 'MSTransitionEnd', + 'transition' : 'transitionend' + }; + + /** + * Expose `transitionend` + */ + + var el = document.createElement('p'); + + for (var transition in map) { + if (null != el.style[transition]) { + transitionEnd = map[transition]; + break; + } + } +})() + +exports.transitionend = transitionEnd + +exports.transition = require('transition-property') + +exports.transform = transform + +exports.touchAction = require('touchaction-property') + +exports.has3d = require('has-translate3d') diff --git a/node_modules/prop-detect/karma.conf.js b/node_modules/prop-detect/karma.conf.js new file mode 100644 index 00000000..5fca3681 --- /dev/null +++ b/node_modules/prop-detect/karma.conf.js @@ -0,0 +1,73 @@ +// Karma configuration +// npm i karma karma-cli karma-firefox-launcher karma-mocha karma-webpack mocha --save-dev +// node_modules/.bin/karma start --single-run +module.exports = function(config) { + config.set({ + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'], + + + // list of files / patterns to load in the browser + files: [ + 'test/test.js' + ], + + // list of files to exclude + exclude: [ + ], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + 'test/test.js': ['webpack'] + }, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress'], + + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + webpack: { + module: { + loaders: [ + {test: /\.html$/, loader: 'html'} + ] + } + }, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['Firefox'], + + webpackMiddleware: { + noInfo: true + }, + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true + }); +}; + diff --git a/node_modules/prop-detect/package.json b/node_modules/prop-detect/package.json new file mode 100644 index 00000000..7b358074 --- /dev/null +++ b/node_modules/prop-detect/package.json @@ -0,0 +1,44 @@ +{ + "name": "prop-detect", + "version": "1.1.0", + "description": "detect the properties in one lib", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/chemzqm/prop-detect.git" + }, + "keywords": [ + "detect", + "property", + "animation" + ], + "author": "chemzqm@gmail.com", + "license": "MIT", + "bugs": { + "url": "https://github.com/chemzqm/prop-detect/issues" + }, + "homepage": "https://github.com/chemzqm/prop-detect#readme", + "devDependencies": { + "karma": "^0.13.15", + "karma-cli": "^0.1.1", + "karma-firefox-launcher": "^0.1.6", + "karma-mocha": "^0.2.0", + "karma-webpack": "^1.7.0", + "karma-wrap-preprocessor": "^0.1.0", + "mocha": "^2.3.3", + "mocha-loader": "^0.7.1", + "webpack": "^1.12.3", + "webpack-dev-server": "^1.12.1" + }, + "dependencies": { + "has-translate3d": "0.0.3", + "touchaction-property": "0.0.1", + "transition-property": "^1.0.1" + } +} diff --git a/node_modules/prop-detect/test/test.js b/node_modules/prop-detect/test/test.js new file mode 100644 index 00000000..adec4088 --- /dev/null +++ b/node_modules/prop-detect/test/test.js @@ -0,0 +1,31 @@ +/*global describe, it*/ +var assert = require('assert') +var detect = require('..') + +describe('prop-detect', function() { + it('should be transition', function () { + assert(/transition/i.test(detect.transition)) + }) + + it('should be transform', function () { + assert(/transform/i.test(detect.transform)) + }) + + it('should be touchAction', function () { + if (detect.touchAction) { + assert.equal('touchAction', detect.touchAction) + } else { + assert.equal(null, detect.touchAction) + } + }) + + it('should be transitionend', function () { + assert(/transition/i.test(detect.transitionend)) + }) + + it('should be has3d', function () { + assert.equal(detect.has3d, true) + }) + + +}) diff --git a/node_modules/touchaction-property/.npmignore b/node_modules/touchaction-property/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/touchaction-property/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/touchaction-property/History.md b/node_modules/touchaction-property/History.md new file mode 100644 index 00000000..2d30b5bf --- /dev/null +++ b/node_modules/touchaction-property/History.md @@ -0,0 +1,6 @@ + +0.0.1 / 2013-11-13 +================== + + * Readme++ + * initial commit diff --git a/node_modules/touchaction-property/Makefile b/node_modules/touchaction-property/Makefile new file mode 100644 index 00000000..0f14dac3 --- /dev/null +++ b/node_modules/touchaction-property/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components template.js + +.PHONY: clean diff --git a/node_modules/touchaction-property/Readme.md b/node_modules/touchaction-property/Readme.md new file mode 100644 index 00000000..7a43e7b5 --- /dev/null +++ b/node_modules/touchaction-property/Readme.md @@ -0,0 +1,19 @@ + +# touchaction-property + + Returns "touchAction", "msTouchAction", or null. + See: http://msdn.microsoft.com/en-us/library/windows/apps/hh767313.aspx + +## Installation + + Install with [component(1)](http://component.io): + + $ component install component/touchaction-property + +## API + + + +## License + + MIT diff --git a/node_modules/touchaction-property/component.json b/node_modules/touchaction-property/component.json new file mode 100644 index 00000000..8b0306fd --- /dev/null +++ b/node_modules/touchaction-property/component.json @@ -0,0 +1,21 @@ +{ + "name": "touchaction-property", + "repo": "component/touchaction-property", + "description": "Returns \"touchAction\", \"msTouchAction\", or null", + "version": "0.0.1", + "keywords": [ + "touch", + "action", + "ms", + "microsoft", + "pointer", + "events" + ], + "dependencies": {}, + "development": {}, + "license": "MIT", + "main": "index.js", + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/touchaction-property/index.js b/node_modules/touchaction-property/index.js new file mode 100644 index 00000000..ca651c02 --- /dev/null +++ b/node_modules/touchaction-property/index.js @@ -0,0 +1,20 @@ + +/** + * Module exports. + */ + +module.exports = touchActionProperty(); + +/** + * Returns "touchAction", "msTouchAction", or null. + */ + +function touchActionProperty(doc) { + if (!doc) doc = document; + var div = doc.createElement('div'); + var prop = null; + if ('touchAction' in div.style) prop = 'touchAction'; + else if ('msTouchAction' in div.style) prop = 'msTouchAction'; + div = null; + return prop; +} diff --git a/node_modules/touchaction-property/package.json b/node_modules/touchaction-property/package.json new file mode 100644 index 00000000..b740e193 --- /dev/null +++ b/node_modules/touchaction-property/package.json @@ -0,0 +1,25 @@ +{ + "name": "touchaction-property", + "repo": "component/touchaction-property", + "description": "Returns \"touchAction\", \"msTouchAction\", or null", + "version": "0.0.1", + "keywords": [ + "touch", + "action", + "ms", + "microsoft", + "pointer", + "events" + ], + "dependencies": {}, + "license": "MIT", + "component": { + "scripts": { + "touchaction-property/index.js": "index.js" + } + }, + "repository": { + "type": "git", + "url": "https://github.com/component/touchaction-property.git" + } +} diff --git a/node_modules/touchaction-property/test/index.html b/node_modules/touchaction-property/test/index.html new file mode 100644 index 00000000..19488ef0 --- /dev/null +++ b/node_modules/touchaction-property/test/index.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/node_modules/transform-property/.npmignore b/node_modules/transform-property/.npmignore new file mode 100644 index 00000000..48a2e246 --- /dev/null +++ b/node_modules/transform-property/.npmignore @@ -0,0 +1,2 @@ +components +build diff --git a/node_modules/transform-property/History.md b/node_modules/transform-property/History.md new file mode 100644 index 00000000..a339d6de --- /dev/null +++ b/node_modules/transform-property/History.md @@ -0,0 +1,5 @@ + +0.0.1 / 2013-04-04 +================== + + * initial release diff --git a/node_modules/transform-property/Makefile b/node_modules/transform-property/Makefile new file mode 100644 index 00000000..0f14dac3 --- /dev/null +++ b/node_modules/transform-property/Makefile @@ -0,0 +1,11 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components template.js + +.PHONY: clean diff --git a/node_modules/transform-property/Readme.md b/node_modules/transform-property/Readme.md new file mode 100644 index 00000000..28474f64 --- /dev/null +++ b/node_modules/transform-property/Readme.md @@ -0,0 +1,17 @@ + +# transform-property + + Name of the CSS transform property (cross-browser) + +## Installation + + $ component install component/transform-property + +## API + + Exports the name of transform property as a `String` or `null` if + the property is not supported. + +## License + + MIT diff --git a/node_modules/transform-property/component.json b/node_modules/transform-property/component.json new file mode 100644 index 00000000..3539f193 --- /dev/null +++ b/node_modules/transform-property/component.json @@ -0,0 +1,13 @@ +{ + "name": "transform-property", + "repo": "component/transform-property", + "description": "Name of the CSS transform property (cross-browser)", + "version": "0.0.1", + "keywords": [], + "dependencies": {}, + "development": {}, + "license": "MIT", + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/transform-property/index.js b/node_modules/transform-property/index.js new file mode 100644 index 00000000..389e8e7c --- /dev/null +++ b/node_modules/transform-property/index.js @@ -0,0 +1,19 @@ + +var styles = [ + 'webkitTransform', + 'MozTransform', + 'msTransform', + 'OTransform', + 'transform' +]; + +var el = document.createElement('p'); +var style; + +for (var i = 0; i < styles.length; i++) { + style = styles[i]; + if (null != el.style[style]) { + module.exports = style; + break; + } +} diff --git a/node_modules/transform-property/package.json b/node_modules/transform-property/package.json new file mode 100644 index 00000000..ad9d8ebc --- /dev/null +++ b/node_modules/transform-property/package.json @@ -0,0 +1,9 @@ +{ + "name": "transform-property", + "version": "0.0.1", + "component": { + "scripts": { + "transform-property/index.js": "index.js" + } + } +} diff --git a/node_modules/transition-property/Makefile b/node_modules/transition-property/Makefile new file mode 100644 index 00000000..532eaaa9 --- /dev/null +++ b/node_modules/transition-property/Makefile @@ -0,0 +1,7 @@ +webpack: + @webpack-dev-server 'mocha!./test/test.js' --hot --inline + +test: + @karma start + +.PHONY: test diff --git a/node_modules/transition-property/Readme.md b/node_modules/transition-property/Readme.md new file mode 100644 index 00000000..e4fb75a5 --- /dev/null +++ b/node_modules/transition-property/Readme.md @@ -0,0 +1,12 @@ +# transition-property + +## Install + + npm i transition-property -S + +## Usage + +``` js +var transitionProperty = require('transition-property') +el.style[transitionProperty] = '100ms -webkit-transform linear' +``` diff --git a/node_modules/transition-property/index.js b/node_modules/transition-property/index.js new file mode 100644 index 00000000..e7e11424 --- /dev/null +++ b/node_modules/transition-property/index.js @@ -0,0 +1,20 @@ +var styles = [ + 'webkitTransition', + 'MozTransition', + 'OTransition', + 'msTransition', + 'transition' +] + +var el = document.createElement('p') +var style + +for (var i = 0; i < styles.length; i++) { + if (null != el.style[styles[i]]) { + style = styles[i] + break + } +} +el = null + +module.exports = style diff --git a/node_modules/transition-property/karma.conf.js b/node_modules/transition-property/karma.conf.js new file mode 100644 index 00000000..de755faa --- /dev/null +++ b/node_modules/transition-property/karma.conf.js @@ -0,0 +1,73 @@ +// Karma configuration +// npm i karma karma-cli karma-firefox-launcher karma-mocha karma-webpack karma-wrap-preprocessor mocha --save-dev +// node_modules/.bin/karma start --single-run +module.exports = function(config) { + config.set({ + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'], + + + // list of files / patterns to load in the browser + files: [ + 'test/test.js' + ], + + // list of files to exclude + exclude: [ + ], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + 'test/test.js': ['webpack'] + }, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress'], + + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + webpack: { + module: { + loaders: [ + {test: /\.html$/, loader: 'html'} + ] + } + }, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['Firefox'], + + webpackMiddleware: { + noInfo: true + }, + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true + }); +}; + diff --git a/node_modules/transition-property/package.json b/node_modules/transition-property/package.json new file mode 100644 index 00000000..36c6ed1f --- /dev/null +++ b/node_modules/transition-property/package.json @@ -0,0 +1,32 @@ +{ + "name": "transition-property", + "version": "1.0.1", + "description": "transition property detect", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/chemzqm/transition-property.git" + }, + "keywords": [ + "transition", + "property" + ], + "author": "chemzqm@gmail.com", + "license": "MIT", + "bugs": { + "url": "https://github.com/chemzqm/transition-property/issues" + }, + "homepage": "https://github.com/chemzqm/transition-property#readme", + "devDependencies": { + "mocha": "^2.3.3", + "mocha-loader": "^0.7.1", + "webpack": "^1.12.3", + "webpack-dev-server": "^1.12.1" + } +} diff --git a/node_modules/transition-property/test/test.js b/node_modules/transition-property/test/test.js new file mode 100644 index 00000000..322dfc59 --- /dev/null +++ b/node_modules/transition-property/test/test.js @@ -0,0 +1,9 @@ +/*global describe, it*/ +var assert = require('assert') +var prop = require('..') + +describe('transition-property', function() { + it('should be transition', function () { + assert.equal(/transition/.test(prop)) + }) +}) diff --git a/src/Model/Utility/utility.ts b/src/Model/Utility/utility.ts index 1c39b64d..8640a8c1 100644 --- a/src/Model/Utility/utility.ts +++ b/src/Model/Utility/utility.ts @@ -277,3 +277,33 @@ export function parseArray(inputString: string): any[] { export function localeCompare(a: string, b: string): number { return a.localeCompare(b); } + +// ui +export function implementPinchZoom(element: HTMLElement) { + let initialDistance = 0; + let pinching = false; + + const distance = (e: TouchEvent) => Math.hypot(e.touches[0].pageX - e.touches[1].pageX, + e.touches[0].pageY - e.touches[1].pageY); + function apply(factor) { + element.style.transform = `scale(${(Math.floor(factor*100)/100).toString()})`; + } + + element.addEventListener("touchstart", (event: TouchEvent) => { + if (event.touches.length != 2) return; + initialDistance = distance(event); + pinching = true; + apply(1); + }); + element.addEventListener("touchend", (event: TouchEvent) => { + if (event.touches.length == 2) return; + pinching = false; + }) + element.addEventListener("touchmove", (event: TouchEvent) => { + if (!pinching) return; + event.preventDefault(); + const currentDistance = distance(event); + const factor = currentDistance / initialDistance; + apply(factor); + }) +} diff --git a/src/View/ChatPages/boardKanbanPage.tsx b/src/View/ChatPages/boardKanbanPage.tsx index c4ddbe24..ef2a7c42 100644 --- a/src/View/ChatPages/boardKanbanPage.tsx +++ b/src/View/ChatPages/boardKanbanPage.tsx @@ -1,4 +1,6 @@ import * as React from "bloatless-react"; +import * as Utility from "../../Model/Utility/utility"; + import { ViewController } from "../viewController"; import { TaskViewModelToEntry } from "../Components/taskEntry"; import { @@ -15,7 +17,7 @@ export function BoardKanbanPage( coreViewModel: CoreViewModel, boardViewModel: BoardViewModel, ) { - return PropertyValueList( + const main = PropertyValueList( "category", (taskViewModel: TaskViewModel) => taskViewModel.task, boardViewModel.filteredTaskViewModels, @@ -47,6 +49,8 @@ export function BoardKanbanPage( ); }, ); + Utility.implementPinchZoom(main); + return main; } function Column( diff --git a/src/View/ChatPages/boardStatusGridPage.tsx b/src/View/ChatPages/boardStatusGridPage.tsx index 5ca1e8cc..1e3cfe0c 100644 --- a/src/View/ChatPages/boardStatusGridPage.tsx +++ b/src/View/ChatPages/boardStatusGridPage.tsx @@ -1,4 +1,6 @@ import * as React from "bloatless-react"; +import * as Utility from "../../Model/Utility/utility"; + import { ViewController } from "../viewController"; import { TaskViewModelToEntry } from "../Components/taskEntry"; import { @@ -40,7 +42,7 @@ export function BoardStatusGridPage( return StatusNameCell(coreViewModel, statusName, index, boardViewModel); }; - return ( + const main = (
      ); + Utility.implementPinchZoom(main); + return main; } function StatusNameCell( diff --git a/src/View/ChatPages/taskPage.css b/src/View/ChatPages/taskPage.css index 91bfc720..4f6ec545 100644 --- a/src/View/ChatPages/taskPage.css +++ b/src/View/ChatPages/taskPage.css @@ -33,11 +33,16 @@ width: 100%; height: 100%; - overflow: auto; + overflow: visible; + transform-origin: top left; padding: var(--content-padding); } +#board-content .main-content { + overflow: auto; +} + #chat-page > div > #main > #task-page .kanban-board-wrapper .kanban-column, #chat-page > div > #main > #task-page .status-grid-wrapper .status-column { display: flex; diff --git a/src/ViewModel/Global/coreViewModel.ts b/src/ViewModel/Global/coreViewModel.ts index eed496d7..ffefdf32 100644 --- a/src/ViewModel/Global/coreViewModel.ts +++ b/src/ViewModel/Global/coreViewModel.ts @@ -9,7 +9,7 @@ import ConnectionModel from "../../Model/Global/connectionModel"; import ChatListModel from "../../Model/Chat/chatListModel"; export default class CoreViewModel { - readonly BUILD = "Build 26.08.30.B"; + readonly BUILD = "Build 26.08.30.C"; translations: Translations; diff --git a/src/index.tsx b/src/index.tsx index 7efc731f..bcd2f431 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,6 +2,7 @@ import * as React from "bloatless-react"; import "./colors.css"; import "./coloredTile.css"; import "./base.css"; +import * as Utility from "./Model/Utility/utility"; import HomeViewModel from "./ViewModel/Pages/homeViewModel"; import StorageViewModel from "./ViewModel/Global/storageViewModel"; import SettingsViewModel from "./ViewModel/Global/settingsViewModel";